diff --git a/gradle/instrumentation.gradle b/gradle/instrumentation.gradle index 3d4a170f25..3d2b9cdb6d 100644 --- a/gradle/instrumentation.gradle +++ b/gradle/instrumentation.gradle @@ -37,10 +37,10 @@ afterEvaluate { implementation deps.slf4j // Include instrumentations instrumenting core JDK classes tp ensure interoperability with other instrumentation - testImplementation project(':instrumentation:executors') + testImplementation project(':instrumentation:executors:javaagent') // FIXME: we should enable this, but currently this fails tests for google http client - //testImplementation project(':instrumentation:http-url-connection') - testImplementation project(':instrumentation:classloaders') + //testImplementation project(':instrumentation:http-url-connection:javaagent') + testImplementation project(':instrumentation:classloaders:javaagent') testImplementation project(':testing-common') testAnnotationProcessor deps.autoservice diff --git a/instrumentation/akka-actor-2.5/akka-actor-2.5.gradle b/instrumentation/akka-actor-2.5/akka-actor-2.5.gradle deleted file mode 100644 index d868c9c556..0000000000 --- a/instrumentation/akka-actor-2.5/akka-actor-2.5.gradle +++ /dev/null @@ -1,18 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply from: "$rootDir/gradle/test-with-scala.gradle" - -muzzle { - pass { - group = 'com.typesafe.akka' - module = 'akka-actor_2.11' - versions = "[2.5.0,)" - } -} - -dependencies { - implementation project(':instrumentation:executors') - compileOnly group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.0' - - testImplementation deps.scala - testImplementation group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.0' -} \ No newline at end of file diff --git a/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java b/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java deleted file mode 100644 index 9864112b7a..0000000000 --- a/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkaactor; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; - -@AutoService(InstrumentationModule.class) -public class AkkaActorInstrumentationModule extends InstrumentationModule { - public AkkaActorInstrumentationModule() { - super("akka-actor", "akka-actor-2.5"); - } - - @Override - public List typeInstrumentations() { - return asList(new AkkaForkJoinPoolInstrumentation(), new AkkaForkJoinTaskInstrumentation()); - } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put(Runnable.class.getName(), State.class.getName()); - map.put(Callable.class.getName(), State.class.getName()); - map.put(AkkaForkJoinTaskInstrumentation.TASK_CLASS_NAME, State.class.getName()); - return Collections.unmodifiableMap(map); - } - - @Override - protected boolean defaultEnabled() { - return false; - } -} diff --git a/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaForkJoinPoolInstrumentation.java b/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaForkJoinPoolInstrumentation.java deleted file mode 100644 index 3238b69cb5..0000000000 --- a/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaForkJoinPoolInstrumentation.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkaactor; - -import static net.bytebuddy.matcher.ElementMatchers.nameMatches; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import akka.dispatch.forkjoin.ForkJoinTask; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class AkkaForkJoinPoolInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - // This might need to be an extendsClass matcher... - return named("akka.dispatch.forkjoin.ForkJoinPool"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("execute") - .and(takesArgument(0, named(AkkaForkJoinTaskInstrumentation.TASK_CLASS_NAME))), - AkkaForkJoinPoolInstrumentation.class.getName() + "$SetAkkaForkJoinStateAdvice"); - transformers.put( - named("submit") - .and(takesArgument(0, named(AkkaForkJoinTaskInstrumentation.TASK_CLASS_NAME))), - AkkaForkJoinPoolInstrumentation.class.getName() + "$SetAkkaForkJoinStateAdvice"); - transformers.put( - nameMatches("invoke") - .and(takesArgument(0, named(AkkaForkJoinTaskInstrumentation.TASK_CLASS_NAME))), - AkkaForkJoinPoolInstrumentation.class.getName() + "$SetAkkaForkJoinStateAdvice"); - return transformers; - } - - public static class SetAkkaForkJoinStateAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static State enterJobSubmit( - @Advice.Argument(value = 0, readOnly = false) ForkJoinTask task) { - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(task)) { - ContextStore contextStore = - InstrumentationContext.get(ForkJoinTask.class, State.class); - return ExecutorInstrumentationUtils.setupState( - contextStore, task, Java8BytecodeBridge.currentContext()); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void exitJobSubmit( - @Advice.Enter State state, @Advice.Thrown Throwable throwable) { - ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); - } - } -} diff --git a/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaForkJoinTaskInstrumentation.java b/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaForkJoinTaskInstrumentation.java deleted file mode 100644 index 645dc006cb..0000000000 --- a/instrumentation/akka-actor-2.5/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaForkJoinTaskInstrumentation.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkaactor; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import akka.dispatch.forkjoin.ForkJoinPool; -import akka.dispatch.forkjoin.ForkJoinTask; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import java.util.concurrent.Callable; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * Instrument {@link ForkJoinTask}. - * - *

Note: There are quite a few separate implementations of {@code ForkJoinTask}/{@code - * ForkJoinPool}: JVM, Akka, Scala, Netty to name a few. This class handles Akka version. - */ -public class AkkaForkJoinTaskInstrumentation implements TypeInstrumentation { - static final String TASK_CLASS_NAME = "akka.dispatch.forkjoin.ForkJoinTask"; - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed(TASK_CLASS_NAME); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named(TASK_CLASS_NAME)); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("exec").and(takesArguments(0)).and(not(isAbstract())), - AkkaForkJoinTaskInstrumentation.class.getName() + "$ForkJoinTaskAdvice"); - } - - public static class ForkJoinTaskAdvice { - - /** - * When {@link ForkJoinTask} object is submitted to {@link ForkJoinPool} as {@link Runnable} or - * {@link Callable} it will not get wrapped, instead it will be casted to {@code ForkJoinTask} - * directly. This means state is still stored in {@code Runnable} or {@code Callable} and we - * need to use that state. - */ - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope enter(@Advice.This ForkJoinTask thiz) { - ContextStore contextStore = - InstrumentationContext.get(ForkJoinTask.class, State.class); - Scope scope = AdviceUtils.startTaskScope(contextStore, thiz); - if (thiz instanceof Runnable) { - ContextStore runnableContextStore = - InstrumentationContext.get(Runnable.class, State.class); - Scope newScope = AdviceUtils.startTaskScope(runnableContextStore, (Runnable) thiz); - if (null != newScope) { - if (null != scope) { - newScope.close(); - } else { - scope = newScope; - } - } - } - if (thiz instanceof Callable) { - ContextStore callableContextStore = - InstrumentationContext.get(Callable.class, State.class); - Scope newScope = AdviceUtils.startTaskScope(callableContextStore, (Callable) thiz); - if (null != newScope) { - if (null != scope) { - newScope.close(); - } else { - scope = newScope; - } - } - } - return scope; - } - - @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/akka-actor-2.5/src/test/groovy/AkkaActorTest.groovy b/instrumentation/akka-actor-2.5/src/test/groovy/AkkaActorTest.groovy deleted file mode 100644 index de93cf3b9c..0000000000 --- a/instrumentation/akka-actor-2.5/src/test/groovy/AkkaActorTest.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner - -class AkkaActorTest extends AgentTestRunner { - - // TODO this test doesn't really depend on otel.instrumentation.akka-actor.enabled=true - // but setting this property here is needed when running both this test - // and AkkaExecutorInstrumentationTest in the run, otherwise get - // "class redefinition failed: attempted to change superclass or interfaces" - // on whichever test runs second - // (related question is what's the purpose of this test if it doesn't depend on any of the - // instrumentation in this module, is it just to verify that the instrumentation doesn't break - // this scenario?) - static { - System.setProperty("otel.instrumentation.akka-actor.enabled", "true") - } - - def "akka #testMethod"() { - setup: - AkkaActors akkaTester = new AkkaActors() - akkaTester."$testMethod"() - - expect: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - attributes { - } - } - span(1) { - name "$expectedGreeting, Akka" - childOf span(0) - attributes { - } - } - } - } - - where: - testMethod | expectedGreeting - "basicTell" | "Howdy" - "basicAsk" | "Howdy" - "basicForward" | "Hello" - } -} diff --git a/instrumentation/akka-actor-2.5/src/test/groovy/AkkaExecutorInstrumentationTest.groovy b/instrumentation/akka-actor-2.5/src/test/groovy/AkkaExecutorInstrumentationTest.groovy deleted file mode 100644 index 1737d3aeaf..0000000000 --- a/instrumentation/akka-actor-2.5/src/test/groovy/AkkaExecutorInstrumentationTest.groovy +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import akka.dispatch.forkjoin.ForkJoinPool -import akka.dispatch.forkjoin.ForkJoinTask -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.sdk.trace.data.SpanData -import java.lang.reflect.InvocationTargetException -import java.util.concurrent.ArrayBlockingQueue -import java.util.concurrent.Callable -import java.util.concurrent.Future -import java.util.concurrent.RejectedExecutionException -import java.util.concurrent.ThreadPoolExecutor -import java.util.concurrent.TimeUnit -import spock.lang.Shared - -/** - * Test executor instrumentation for Akka specific classes. - * This is to large extent a copy of ExecutorInstrumentationTest. - */ -class AkkaExecutorInstrumentationTest extends AgentTestRunner { - - static { - System.setProperty("otel.instrumentation.akka-actor.enabled", "true") - } - - @Shared - def executeRunnable = { e, c -> e.execute((Runnable) c) } - @Shared - def akkaExecuteForkJoinTask = { e, c -> e.execute((ForkJoinTask) c) } - @Shared - def submitRunnable = { e, c -> e.submit((Runnable) c) } - @Shared - def submitCallable = { e, c -> e.submit((Callable) c) } - @Shared - def akkaSubmitForkJoinTask = { e, c -> e.submit((ForkJoinTask) c) } - @Shared - def akkaInvokeForkJoinTask = { e, c -> e.invoke((ForkJoinTask) c) } - - def "#poolName '#name' propagates"() { - setup: - def pool = poolImpl - def m = method - - new Runnable() { - @Override - void run() { - runUnderTrace("parent") { - // this child will have a span - def child1 = new AkkaAsyncChild() - // this child won't - def child2 = new AkkaAsyncChild(false, false) - m(pool, child1) - m(pool, child2) - child1.waitForCompletion() - child2.waitForCompletion() - } - } - }.run() - - TEST_WRITER.waitForTraces(1) - List trace = TEST_WRITER.traces[0] - - expect: - TEST_WRITER.traces.size() == 1 - trace.size() == 2 - trace.get(0).name == "parent" - trace.get(1).name == "asyncChild" - trace.get(1).parentSpanId == trace.get(0).spanId - - cleanup: - pool?.shutdown() - - // Unfortunately, there's no simple way to test the cross product of methods/pools. - where: - name | method | poolImpl - "execute Runnable" | executeRunnable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "submit Runnable" | submitRunnable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "submit Callable" | submitCallable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - - // ForkJoinPool has additional set of method overloads for ForkJoinTask to deal with - "execute Runnable" | executeRunnable | new ForkJoinPool() - "execute ForkJoinTask" | akkaExecuteForkJoinTask | new ForkJoinPool() - "submit Runnable" | submitRunnable | new ForkJoinPool() - "submit Callable" | submitCallable | new ForkJoinPool() - "submit ForkJoinTask" | akkaSubmitForkJoinTask | new ForkJoinPool() - "invoke ForkJoinTask" | akkaInvokeForkJoinTask | new ForkJoinPool() - poolName = poolImpl.class.name - } - - def "ForkJoinPool '#name' reports after canceled jobs"() { - setup: - def pool = poolImpl - def m = method - List children = new ArrayList<>() - List jobFutures = new ArrayList<>() - - new Runnable() { - @Override - void run() { - runUnderTrace("parent") { - try { - for (int i = 0; i < 20; ++i) { - // Our current instrumentation instrumentation does not behave very well - // if we try to reuse Callable/Runnable. Namely we would be getting 'orphaned' - // child traces sometimes since state can contain only one parent span - and - // we do not really have a good way for attributing work to correct parent span - // if we reuse Callable/Runnable. - // Solution for now is to never reuse a Callable/Runnable. - AkkaAsyncChild child = new AkkaAsyncChild(false, true) - children.add(child) - try { - Future f = m(pool, child) - jobFutures.add(f) - } catch (InvocationTargetException e) { - throw e.getCause() - } - } - } catch (RejectedExecutionException ignored) { - } - - for (Future f : jobFutures) { - f.cancel(false) - } - for (AkkaAsyncChild child : children) { - child.unblock() - } - } - } - }.run() - - TEST_WRITER.waitForTraces(1) - - expect: - TEST_WRITER.traces.size() == 1 - - where: - name | method | poolImpl - "submit Runnable" | submitRunnable | new ForkJoinPool() - "submit Callable" | submitCallable | new ForkJoinPool() - } -} diff --git a/instrumentation/akka-actor-2.5/src/test/scala/AkkaActors.scala b/instrumentation/akka-actor-2.5/src/test/scala/AkkaActors.scala deleted file mode 100644 index 015c0f4475..0000000000 --- a/instrumentation/akka-actor-2.5/src/test/scala/AkkaActors.scala +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem, Props} -import akka.pattern.ask -import akka.util.Timeout -import io.opentelemetry.api.OpenTelemetry -import io.opentelemetry.context.Context -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge -import io.opentelemetry.api.trace.Tracer - -import scala.concurrent.duration._ - -// ! == send-message -object AkkaActors { - val tracer: Tracer = - Java8BytecodeBridge.getGlobalTracer("io.opentelemetry.auto") - - val system: ActorSystem = ActorSystem("helloAkka") - - val printer: ActorRef = system.actorOf(Receiver.props, "receiverActor") - - val howdyGreeter: ActorRef = - system.actorOf(Greeter.props("Howdy", printer), "howdyGreeter") - - val forwarder: ActorRef = - system.actorOf(Forwarder.props(printer), "forwarderActor") - val helloGreeter: ActorRef = - system.actorOf(Greeter.props("Hello", forwarder), "helloGreeter") - - def tracedChild(opName: String): Unit = { - tracer.spanBuilder(opName).startSpan().end() - } -} - -class AkkaActors { - - import AkkaActors._ - import Greeter._ - - implicit val timeout: Timeout = 5.minutes - - def basicTell(): Unit = { - val parentSpan = tracer.spanBuilder("parent").startSpan() - val parentScope = - Java8BytecodeBridge.currentContext().`with`(parentSpan).makeCurrent() - try { - howdyGreeter ! WhoToGreet("Akka") - howdyGreeter ! Greet - } finally { - parentSpan.end() - parentScope.close() - } - } - - def basicAsk(): Unit = { - val parentSpan = tracer.spanBuilder("parent").startSpan() - val parentScope = - Java8BytecodeBridge.currentContext().`with`(parentSpan).makeCurrent() - try { - howdyGreeter ! WhoToGreet("Akka") - howdyGreeter ? Greet - } finally { - parentSpan.end() - parentScope.close() - } - } - - def basicForward(): Unit = { - val parentSpan = tracer.spanBuilder("parent").startSpan() - val parentScope = - Java8BytecodeBridge.currentContext().`with`(parentSpan).makeCurrent() - try { - helloGreeter ! WhoToGreet("Akka") - helloGreeter ? Greet - } finally { - parentSpan.end() - parentScope.close() - } - } -} - -object Greeter { - def props(message: String, receiverActor: ActorRef): Props = - Props(new Greeter(message, receiverActor)) - - final case class WhoToGreet(who: String) - - case object Greet - -} - -class Greeter(message: String, receiverActor: ActorRef) extends Actor { - - import Greeter._ - import Receiver._ - - var greeting = "" - - def receive = { - case WhoToGreet(who) => - greeting = s"$message, $who" - case Greet => - receiverActor ! Greeting(greeting) - } -} - -object Receiver { - def props: Props = Props[Receiver] - - final case class Greeting(greeting: String) - -} - -class Receiver extends Actor with ActorLogging { - - import Receiver._ - - def receive = { - case Greeting(greeting) => { - AkkaActors.tracedChild(greeting) - } - - } -} - -object Forwarder { - def props(receiverActor: ActorRef): Props = - Props(new Forwarder(receiverActor)) -} - -class Forwarder(receiverActor: ActorRef) extends Actor with ActorLogging { - def receive = { - case msg => { - receiverActor forward msg - } - } -} diff --git a/instrumentation/akka-actor-2.5/src/test/scala/AkkaAsyncChild.java b/instrumentation/akka-actor-2.5/src/test/scala/AkkaAsyncChild.java deleted file mode 100644 index 33098dd58e..0000000000 --- a/instrumentation/akka-actor-2.5/src/test/scala/AkkaAsyncChild.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import akka.dispatch.forkjoin.ForkJoinTask; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; - -public class AkkaAsyncChild extends ForkJoinTask implements Runnable, Callable { - private static final Tracer tracer = OpenTelemetry.getGlobalTracer("io.opentelemetry.auto"); - - private final AtomicBoolean blockThread; - private final boolean doTraceableWork; - private final CountDownLatch latch = new CountDownLatch(1); - - public AkkaAsyncChild() { - this(true, false); - } - - @Override - public Object getRawResult() { - return null; - } - - @Override - protected void setRawResult(Object value) {} - - @Override - protected boolean exec() { - runImpl(); - return true; - } - - public AkkaAsyncChild(boolean doTraceableWork, boolean blockThread) { - this.doTraceableWork = doTraceableWork; - this.blockThread = new AtomicBoolean(blockThread); - } - - public void unblock() { - blockThread.set(false); - } - - @Override - public void run() { - runImpl(); - } - - @Override - public Object call() { - runImpl(); - return null; - } - - public void waitForCompletion() throws InterruptedException { - latch.await(); - } - - private void runImpl() { - while (blockThread.get()) { - // busy-wait to block thread - } - if (doTraceableWork) { - asyncChild(); - } - latch.countDown(); - } - - private void asyncChild() { - tracer.spanBuilder("asyncChild").startSpan().end(); - } -} diff --git a/instrumentation/akka-http-10.0/akka-http-10.0.gradle b/instrumentation/akka-http-10.0/akka-http-10.0.gradle deleted file mode 100644 index beedc935d3..0000000000 --- a/instrumentation/akka-http-10.0/akka-http-10.0.gradle +++ /dev/null @@ -1,70 +0,0 @@ -ext { - // TODO remove once Scala/akka supports Java 15 - // https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html - maxJavaVersionForTests = JavaVersion.VERSION_14 -} - -apply from: "$rootDir/gradle/instrumentation.gradle" -apply from: "$rootDir/gradle/test-with-scala.gradle" -apply plugin: 'org.unbroken-dome.test-sets' - -testSets { - version101Test { - dirName = 'test' - } -} - -muzzle { - pass { - group = 'com.typesafe.akka' - module = 'akka-http_2.11' - versions = "[10.0.0,10.1.0)" - // later versions of akka-http expect streams to be provided - extraDependency 'com.typesafe.akka:akka-stream_2.11:2.4.14' - } - pass { - group = 'com.typesafe.akka' - module = 'akka-http_2.12' - versions = "[10.0.0,10.1.0)" - // later versions of akka-http expect streams to be provided - extraDependency 'com.typesafe.akka:akka-stream_2.12:2.4.14' - } - pass { - group = 'com.typesafe.akka' - module = 'akka-http_2.11' - versions = "[10.1.0,)" - // later versions of akka-http expect streams to be provided - extraDependency 'com.typesafe.akka:akka-stream_2.11:2.5.11' - } - pass { - group = 'com.typesafe.akka' - module = 'akka-http_2.12' - versions = "[10.1.0,)" - // later versions of akka-http expect streams to be provided - extraDependency 'com.typesafe.akka:akka-stream_2.12:2.5.11' - } - //There is no akka-http 10.0.x series for scala 2.13 - pass { - group = 'com.typesafe.akka' - module = 'akka-http_2.13' - versions = "[10.1.8,)" - // later versions of akka-http expect streams to be provided - extraDependency 'com.typesafe.akka:akka-stream_2.13:2.5.23' - } -} - -dependencies { - library group: 'com.typesafe.akka', name: 'akka-http_2.11', version: '10.0.0' - library group: 'com.typesafe.akka', name: 'akka-stream_2.11', version: '2.4.14' - - // There are some internal API changes in 10.1 that we would like to test separately for - version101TestImplementation group: 'com.typesafe.akka', name: 'akka-http_2.11', version: '10.1.0' - version101TestImplementation group: 'com.typesafe.akka', name: 'akka-stream_2.11', version: '2.5.11' -} - -test.dependsOn version101Test - -compileVersion101TestGroovy { - classpath = classpath.plus(files(compileVersion101TestScala.destinationDir)) - dependsOn compileVersion101TestScala -} diff --git a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpClientInstrumentationModule.java b/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpClientInstrumentationModule.java deleted file mode 100644 index 7c8f115ab0..0000000000 --- a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpClientInstrumentationModule.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkahttp; - -import static io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpClientTracer.tracer; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import akka.http.javadsl.model.headers.RawHeader; -import akka.http.scaladsl.HttpExt; -import akka.http.scaladsl.model.HttpRequest; -import akka.http.scaladsl.model.HttpResponse; -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import scala.concurrent.Future; -import scala.runtime.AbstractFunction1; -import scala.util.Try; - -@AutoService(InstrumentationModule.class) -public class AkkaHttpClientInstrumentationModule extends InstrumentationModule { - public AkkaHttpClientInstrumentationModule() { - super("akka-http", "akka-http-client"); - } - - @Override - public List typeInstrumentations() { - return Collections.singletonList(new HttpExtInstrumentation()); - } - - public static class HttpExtInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("akka.http.scaladsl.HttpExt"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - // This is mainly for compatibility with 10.0 - transformers.put( - named("singleRequest") - .and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))), - AkkaHttpClientInstrumentationModule.class.getName() + "$SingleRequestAdvice"); - // This is for 10.1+ - transformers.put( - named("singleRequestImpl") - .and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))), - AkkaHttpClientInstrumentationModule.class.getName() + "$SingleRequestAdvice"); - return transformers; - } - } - - public static class SingleRequestAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(value = 0, readOnly = false) HttpRequest request, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - /* - Versions 10.0 and 10.1 have slightly different structure that is hard to distinguish so here - we cast 'wider net' and avoid instrumenting twice. - In the future we may want to separate these, but since lots of code is reused we would need to come up - with way of continuing to reusing it. - */ - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(request); - // Request is immutable, so we have to assign new value once we update headers - AkkaHttpHeaders headers = new AkkaHttpHeaders(request); - scope = tracer().startScope(span, headers); - request = headers.getRequest(); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Argument(0) HttpRequest request, - @Advice.This HttpExt thiz, - @Advice.Return Future responseFuture, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable == null) { - responseFuture.onComplete(new OnCompleteHandler(span), thiz.system().dispatcher()); - } else { - tracer().endExceptionally(span, throwable); - } - } - } - } - - public static class OnCompleteHandler extends AbstractFunction1, Void> { - private final Span span; - - public OnCompleteHandler(Span span) { - this.span = span; - } - - @Override - public Void apply(Try result) { - if (result.isSuccess()) { - tracer().end(span, result.get()); - } else { - tracer().endExceptionally(span, result.failed().get()); - } - return null; - } - } - - public static class AkkaHttpHeaders { - private HttpRequest request; - - public AkkaHttpHeaders(HttpRequest request) { - this.request = request; - } - - public HttpRequest getRequest() { - return request; - } - - public void setRequest(HttpRequest request) { - this.request = request; - } - } - - public static class InjectAdapter implements TextMapPropagator.Setter { - - public static final InjectAdapter SETTER = new InjectAdapter(); - - @Override - public void set(AkkaHttpHeaders carrier, String key, String value) { - HttpRequest request = carrier.getRequest(); - if (request != null) { - // It looks like this cast is only needed in Java, Scala would have figured it out - carrier.setRequest((HttpRequest) request.addHeader(RawHeader.create(key, value))); - } - } - } -} diff --git a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpClientTracer.java b/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpClientTracer.java deleted file mode 100644 index 90366dd866..0000000000 --- a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpClientTracer.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkahttp; - -import static io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpClientInstrumentationModule.InjectAdapter.SETTER; - -import akka.http.javadsl.model.HttpHeader; -import akka.http.scaladsl.HttpExt; -import akka.http.scaladsl.model.HttpRequest; -import akka.http.scaladsl.model.HttpResponse; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpClientInstrumentationModule.AkkaHttpHeaders; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import java.net.URI; -import java.net.URISyntaxException; - -public class AkkaHttpClientTracer - extends HttpClientTracer { - private static final AkkaHttpClientTracer TRACER = new AkkaHttpClientTracer(); - - public static AkkaHttpClientTracer tracer() { - return TRACER; - } - - public Depth getCallDepth() { - return CallDepthThreadLocalMap.getCallDepth(HttpExt.class); - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.method().value(); - } - - @Override - protected URI url(HttpRequest httpRequest) throws URISyntaxException { - return new URI(httpRequest.uri().toString()); - } - - @Override - protected String flavor(HttpRequest httpRequest) { - return httpRequest.protocol().value(); - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.status().intValue(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.getHeader(name).map(HttpHeader::value).orElse(null); - } - - @Override - protected String responseHeader(HttpResponse httpResponse, String name) { - return httpResponse.getHeader(name).map(HttpHeader::value).orElse(null); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.akka-http"; - } -} diff --git a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerHeaders.java b/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerHeaders.java deleted file mode 100644 index 0b74a92c44..0000000000 --- a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerHeaders.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkahttp; - -import akka.http.javadsl.model.HttpHeader; -import akka.http.scaladsl.model.HttpRequest; -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -public class AkkaHttpServerHeaders implements TextMapPropagator.Getter { - - public static final AkkaHttpServerHeaders GETTER = new AkkaHttpServerHeaders(); - - @Override - public Iterable keys(HttpRequest httpRequest) { - return StreamSupport.stream(httpRequest.getHeaders().spliterator(), false) - .map(HttpHeader::lowercaseName) - .collect(Collectors.toList()); - } - - @Override - public String get(HttpRequest carrier, String key) { - Optional header = carrier.getHeader(key); - if (header.isPresent()) { - return header.get().value(); - } else { - return null; - } - } -} diff --git a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerInstrumentationModule.java b/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerInstrumentationModule.java deleted file mode 100644 index 750f44fea2..0000000000 --- a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerInstrumentationModule.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkahttp; - -import static io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpServerTracer.tracer; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import akka.http.scaladsl.model.HttpRequest; -import akka.http.scaladsl.model.HttpResponse; -import akka.stream.Materializer; -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import scala.Function1; -import scala.concurrent.ExecutionContext; -import scala.concurrent.Future; -import scala.runtime.AbstractFunction1; - -@AutoService(InstrumentationModule.class) -public class AkkaHttpServerInstrumentationModule extends InstrumentationModule { - public AkkaHttpServerInstrumentationModule() { - super("akka-http", "akka-http-server"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HttpExtInstrumentation()); - } - - public static class HttpExtInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("akka.http.scaladsl.HttpExt"); - } - - @Override - public Map, String> transformers() { - // Instrumenting akka-streams bindAndHandle api was previously attempted. - // This proved difficult as there was no clean way to close the async scope - // in the graph logic after the user's request handler completes. - // - // Instead, we're instrumenting the bindAndHandle function helpers by - // wrapping the scala functions with our own handlers. - Map, String> transformers = new HashMap<>(); - transformers.put( - named("bindAndHandleSync").and(takesArgument(0, named("scala.Function1"))), - AkkaHttpServerInstrumentationModule.class.getName() + "$AkkaHttpSyncAdvice"); - transformers.put( - named("bindAndHandleAsync").and(takesArgument(0, named("scala.Function1"))), - AkkaHttpServerInstrumentationModule.class.getName() + "$AkkaHttpAsyncAdvice"); - return transformers; - } - } - - public static class AkkaHttpSyncAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void wrapHandler( - @Advice.Argument(value = 0, readOnly = false) - Function1 handler) { - handler = new SyncWrapper(handler); - } - } - - public static class AkkaHttpAsyncAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void wrapHandler( - @Advice.Argument(value = 0, readOnly = false) - Function1> handler, - @Advice.Argument(7) Materializer materializer) { - handler = new AsyncWrapper(handler, materializer.executionContext()); - } - } - - public static class SyncWrapper extends AbstractFunction1 { - private final Function1 userHandler; - - public SyncWrapper(Function1 userHandler) { - this.userHandler = userHandler; - } - - @Override - public HttpResponse apply(HttpRequest request) { - Context ctx = tracer().startSpan(request, request, "akka.request"); - Span span = Java8BytecodeBridge.spanFromContext(ctx); - try (Scope ignored = tracer().startScope(span, null)) { - HttpResponse response = userHandler.apply(request); - tracer().end(span, response); - return response; - } catch (Throwable t) { - tracer().endExceptionally(span, t); - throw t; - } - } - } - - public static class AsyncWrapper extends AbstractFunction1> { - private final Function1> userHandler; - private final ExecutionContext executionContext; - - public AsyncWrapper( - Function1> userHandler, - ExecutionContext executionContext) { - this.userHandler = userHandler; - this.executionContext = executionContext; - } - - @Override - public Future apply(HttpRequest request) { - Context ctx = tracer().startSpan(request, request, "akka.request"); - Span span = Java8BytecodeBridge.spanFromContext(ctx); - try (Scope ignored = tracer().startScope(span, null)) { - return userHandler - .apply(request) - .transform( - new AbstractFunction1() { - @Override - public HttpResponse apply(HttpResponse response) { - tracer().end(span, response); - return response; - } - }, - new AbstractFunction1() { - @Override - public Throwable apply(Throwable t) { - tracer().endExceptionally(span, t); - return t; - } - }, - executionContext); - } catch (Throwable t) { - tracer().endExceptionally(span, t); - throw t; - } - } - } -} diff --git a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerTracer.java b/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerTracer.java deleted file mode 100644 index 803c685c96..0000000000 --- a/instrumentation/akka-http-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerTracer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.akkahttp; - -import akka.http.javadsl.model.HttpHeader; -import akka.http.scaladsl.model.HttpRequest; -import akka.http.scaladsl.model.HttpResponse; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer; - -public class AkkaHttpServerTracer - extends HttpServerTracer { - private static final AkkaHttpServerTracer TRACER = new AkkaHttpServerTracer(); - - public static AkkaHttpServerTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.method().value(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.getHeader(name).map(HttpHeader::value).orElse(null); - } - - @Override - protected int responseStatus(HttpResponse httpResponse) { - return httpResponse.status().intValue(); - } - - @Override - protected void attachServerContext(Context context, Void none) {} - - @Override - public Context getServerContext(Void none) { - return null; - } - - @Override - protected String url(HttpRequest httpRequest) { - return httpRequest.uri().toString(); - } - - @Override - protected String peerHostIP(HttpRequest httpRequest) { - return null; - } - - @Override - protected String flavor(HttpRequest connection, HttpRequest request) { - return connection.protocol().value(); - } - - @Override - protected Getter getGetter() { - return AkkaHttpServerHeaders.GETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.akka-http"; - } - - @Override - protected Integer peerPort(HttpRequest httpRequest) { - return null; - } -} diff --git a/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy b/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy deleted file mode 100644 index 317dc87516..0000000000 --- a/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpClientInstrumentationTest.groovy +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import akka.actor.ActorSystem -import akka.http.javadsl.Http -import akka.http.javadsl.model.HttpMethods -import akka.http.javadsl.model.HttpRequest -import akka.http.javadsl.model.headers.RawHeader -import akka.stream.ActorMaterializer -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class AkkaHttpClientInstrumentationTest extends HttpClientTest { - - @Shared - ActorSystem system = ActorSystem.create() - @Shared - ActorMaterializer materializer = ActorMaterializer.create(system) - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = HttpRequest.create(uri.toString()) - .withMethod(HttpMethods.lookup(method).get()) - .addHeaders(headers.collect { RawHeader.create(it.key, it.value) }) - - def response = Http.get(system) - .singleRequest(request, materializer) - //.whenComplete { result, error -> - // FIXME: Callback should be here instead. - // callback?.call() - //} - .toCompletableFuture() - .get() - callback?.call() - return response.status().intValue() - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testRemoteConnection() { - // Not sure how to properly set timeouts... - return false - } - - def "singleRequest exception trace"() { - when: - // Passing null causes NPE in singleRequest - Http.get(system).singleRequest(null, materializer) - - then: - thrown NullPointerException - assertTraces(1) { - trace(0, 1) { - span(0) { - hasNoParent() - name HttpClientTracer.DEFAULT_SPAN_NAME - kind CLIENT - errored true - errorEvent(NullPointerException) - } - } - } - } -} diff --git a/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy b/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy deleted file mode 100644 index 9ae8412e92..0000000000 --- a/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpServerTest - -abstract class AkkaHttpServerInstrumentationTest extends HttpServerTest { - - @Override - boolean testExceptionBody() { - false - } - -// FIXME: This doesn't work because we don't support bindAndHandle. -// @Override -// def startServer(int port) { -// AkkaHttpTestWebServer.start(port) -// } -// -// @Override -// void stopServer(Object ignore) { -// AkkaHttpTestWebServer.stop() -// } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "akka.request" - } -} - -class AkkaHttpServerInstrumentationTestSync extends AkkaHttpServerInstrumentationTest { - @Override - def startServer(int port) { - AkkaHttpTestSyncWebServer.start(port) - } - - @Override - void stopServer(Object ignore) { - AkkaHttpTestSyncWebServer.stop() - } -} - -class AkkaHttpServerInstrumentationTestAsync extends AkkaHttpServerInstrumentationTest { - @Override - def startServer(int port) { - AkkaHttpTestAsyncWebServer.start(port) - } - - @Override - void stopServer(Object ignore) { - AkkaHttpTestAsyncWebServer.stop() - } -} diff --git a/instrumentation/akka-http-10.0/src/test/resources/application.conf b/instrumentation/akka-http-10.0/src/test/resources/application.conf deleted file mode 100644 index 7e7db62412..0000000000 --- a/instrumentation/akka-http-10.0/src/test/resources/application.conf +++ /dev/null @@ -1,6 +0,0 @@ -akka.http { - host-connection-pool { - // Limit maximum http backoff for tests - max-connection-backoff = 100ms - } -} diff --git a/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestAsyncWebServer.scala b/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestAsyncWebServer.scala deleted file mode 100644 index 9b7e695142..0000000000 --- a/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestAsyncWebServer.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.Http.ServerBinding -import akka.http.scaladsl.model.HttpMethods.GET -import akka.http.scaladsl.model._ -import akka.stream.ActorMaterializer -import groovy.lang.Closure -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ - -import scala.concurrent.{Await, ExecutionContextExecutor, Future} - -object AkkaHttpTestAsyncWebServer { - implicit val system: ActorSystem = ActorSystem("my-system") - implicit val materializer: ActorMaterializer = ActorMaterializer() - // needed for the future flatMap/onComplete in the end - implicit val executionContext: ExecutionContextExecutor = system.dispatcher - val asyncHandler: HttpRequest => Future[HttpResponse] = { - case HttpRequest(GET, uri: Uri, _, _, _) => - Future { - val endpoint = - HttpServerTest.ServerEndpoint.forPath(uri.path.toString()) - HttpServerTest.controller( - endpoint, - new Closure[HttpResponse](()) { - def doCall(): HttpResponse = { - val resp = HttpResponse(status = endpoint.getStatus) //.withHeaders(headers.Type)resp.contentType = "text/plain" - endpoint match { - case SUCCESS => resp.withEntity(endpoint.getBody) - case QUERY_PARAM => resp.withEntity(uri.queryString().orNull) - case REDIRECT => - resp.withHeaders(headers.Location(endpoint.getBody)) - case ERROR => resp.withEntity(endpoint.getBody) - case EXCEPTION => throw new Exception(endpoint.getBody) - case _ => - HttpResponse(status = NOT_FOUND.getStatus) - .withEntity(NOT_FOUND.getBody) - } - } - } - ) - } - } - - private var binding: ServerBinding = _ - - def start(port: Int): Unit = synchronized { - if (null == binding) { - import scala.concurrent.duration._ - binding = Await.result( - Http().bindAndHandleAsync(asyncHandler, "localhost", port), - 10 seconds - ) - } - } - - def stop(): Unit = synchronized { - if (null != binding) { - binding.unbind() - system.terminate() - binding = null - } - } -} diff --git a/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestSyncWebServer.scala b/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestSyncWebServer.scala deleted file mode 100644 index 010a820d50..0000000000 --- a/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestSyncWebServer.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.Http.ServerBinding -import akka.http.scaladsl.model.HttpMethods.GET -import akka.http.scaladsl.model._ -import akka.stream.ActorMaterializer -import groovy.lang.Closure -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ - -import scala.concurrent.Await - -object AkkaHttpTestSyncWebServer { - implicit val system = ActorSystem("my-system") - implicit val materializer = ActorMaterializer() - // needed for the future flatMap/onComplete in the end - implicit val executionContext = system.dispatcher - val syncHandler: HttpRequest => HttpResponse = { - case HttpRequest(GET, uri: Uri, _, _, _) => { - val endpoint = HttpServerTest.ServerEndpoint.forPath(uri.path.toString()) - HttpServerTest.controller( - endpoint, - new Closure[HttpResponse](()) { - def doCall(): HttpResponse = { - val resp = HttpResponse(status = endpoint.getStatus) - endpoint match { - case SUCCESS => resp.withEntity(endpoint.getBody) - case QUERY_PARAM => resp.withEntity(uri.queryString().orNull) - case REDIRECT => - resp.withHeaders(headers.Location(endpoint.getBody)) - case ERROR => resp.withEntity(endpoint.getBody) - case EXCEPTION => throw new Exception(endpoint.getBody) - case _ => - HttpResponse(status = NOT_FOUND.getStatus) - .withEntity(NOT_FOUND.getBody) - } - } - } - ) - } - } - - private var binding: ServerBinding = null - - def start(port: Int): Unit = synchronized { - if (null == binding) { - import scala.concurrent.duration._ - binding = Await.result( - Http().bindAndHandleSync(syncHandler, "localhost", port), - 10 seconds - ) - } - } - - def stop(): Unit = synchronized { - if (null != binding) { - binding.unbind() - system.terminate() - binding = null - } - } -} diff --git a/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestWebServer.scala b/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestWebServer.scala deleted file mode 100644 index a96f4e72ce..0000000000 --- a/instrumentation/akka-http-10.0/src/test/scala/AkkaHttpTestWebServer.scala +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.Http.ServerBinding -import akka.http.scaladsl.model._ -import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.ExceptionHandler -import akka.stream.ActorMaterializer -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ - -import scala.concurrent.Await - -// FIXME: This doesn't work because we don't support bindAndHandle. -object AkkaHttpTestWebServer { - implicit val system = ActorSystem("my-system") - implicit val materializer = ActorMaterializer() - // needed for the future flatMap/onComplete in the end - implicit val executionContext = system.dispatcher - - val exceptionHandler = ExceptionHandler { - case ex: Exception => - complete( - HttpResponse(status = EXCEPTION.getStatus).withEntity(ex.getMessage) - ) - } - - val route = { //handleExceptions(exceptionHandler) { - path(SUCCESS.rawPath) { - complete( - HttpResponse(status = SUCCESS.getStatus).withEntity(SUCCESS.getBody) - ) - } ~ path(QUERY_PARAM.rawPath) { - complete( - HttpResponse(status = QUERY_PARAM.getStatus).withEntity(SUCCESS.getBody) - ) - } ~ path(REDIRECT.rawPath) { - redirect(Uri(REDIRECT.getBody), StatusCodes.Found) - } ~ path(ERROR.rawPath) { - complete(HttpResponse(status = ERROR.getStatus).withEntity(ERROR.getBody)) - } ~ path(EXCEPTION.rawPath) { - failWith(new Exception(EXCEPTION.getBody)) - } - } - - private var binding: ServerBinding = null - - def start(port: Int): Unit = synchronized { - if (null == binding) { - import scala.concurrent.duration._ - binding = - Await.result(Http().bindAndHandle(route, "localhost", port), 10 seconds) - } - } - - def stop(): Unit = synchronized { - if (null != binding) { - binding.unbind() - system.terminate() - binding = null - } - } -} diff --git a/instrumentation/apache-camel-2.20/apache-camel-2.20.gradle b/instrumentation/apache-camel-2.20/apache-camel-2.20.gradle deleted file mode 100644 index 590fe333f4..0000000000 --- a/instrumentation/apache-camel-2.20/apache-camel-2.20.gradle +++ /dev/null @@ -1,40 +0,0 @@ -ext { - minJavaVersionForTests = JavaVersion.VERSION_1_8 -} - -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.camel" - module = "camel-core" - versions = "[2.20.1,3)" - } -} - -dependencies { - library group: 'org.apache.camel', name: 'camel-core', version: '2.20.1' - - testLibrary group: 'org.apache.camel', name: 'camel-spring-boot-starter', version: '2.20.1' - testLibrary group: 'org.apache.camel', name: 'camel-jetty-starter', version: '2.20.1' - testLibrary group: 'org.apache.camel', name: 'camel-http-starter', version: '2.20.1' - testLibrary group: 'org.apache.camel', name: 'camel-jaxb-starter', version: '2.20.1' - testLibrary group: 'org.apache.camel', name: 'camel-undertow', version: '2.20.1' - - testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-2.0') - testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') - - testImplementation group: 'org.spockframework', name: 'spock-spring', version: "$versions.spock" - - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '1.5.17.RELEASE' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: '1.5.17.RELEASE' - - testImplementation 'javax.xml.bind:jaxb-api:2.3.1' - - latestDepTestLibrary group: 'org.apache.camel', name: 'camel-core', version: '2.+' - latestDepTestLibrary group: 'org.apache.camel', name: 'camel-spring-boot-starter', version: '2.+' - latestDepTestLibrary group: 'org.apache.camel', name: 'camel-jetty-starter', version: '2.+' - latestDepTestLibrary group: 'org.apache.camel', name: 'camel-http-starter', version: '2.+' - latestDepTestLibrary group: 'org.apache.camel', name: 'camel-jaxb-starter', version: '2.+' - latestDepTestLibrary group: 'org.apache.camel', name: 'camel-undertow', version: '2.+' -} diff --git a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/DirectConfig.groovy b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/DirectConfig.groovy index f10867085d..d0b3d22c2d 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/DirectConfig.groovy +++ b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/DirectConfig.groovy @@ -22,7 +22,7 @@ class DirectConfig { @Override void configure() throws Exception { from("direct:receiver") - .log(LoggingLevel.INFO, "test","RECEIVER got: \${body}") + .log(LoggingLevel.INFO, "test", "RECEIVER got: \${body}") .delay(simple("2000")) .setBody(constant("result")) } @@ -36,9 +36,9 @@ class DirectConfig { @Override void configure() throws Exception { from("direct:input") - .log(LoggingLevel.INFO, "test","SENDING request \${body}") + .log(LoggingLevel.INFO, "test", "SENDING request \${body}") .to("direct:receiver") - .log(LoggingLevel.INFO, "test","RECEIVED response \${body}") + .log(LoggingLevel.INFO, "test", "RECEIVED response \${body}") } } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/MulticastConfig.groovy b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/MulticastConfig.groovy index 39e3f76bbc..6fdd74d687 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/MulticastConfig.groovy +++ b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/MulticastConfig.groovy @@ -22,7 +22,7 @@ class MulticastConfig { @Override void configure() throws Exception { from("direct:first") - .log(LoggingLevel.INFO, "test","FIRST request: \${body}") + .log(LoggingLevel.INFO, "test", "FIRST request: \${body}") .delay(simple("1000")) .setBody(constant("first")) } @@ -36,7 +36,7 @@ class MulticastConfig { @Override void configure() throws Exception { from("direct:second") - .log(LoggingLevel.INFO, "test","SECOND request: \${body}") + .log(LoggingLevel.INFO, "test", "SECOND request: \${body}") .delay(simple("2000")) .setBody(constant("second")) } @@ -50,12 +50,12 @@ class MulticastConfig { @Override void configure() throws Exception { from("direct:input") - .log(LoggingLevel.INFO, "test","SENDING request \${body}") + .log(LoggingLevel.INFO, "test", "SENDING request \${body}") .multicast() .parallelProcessing() .to("direct:first", "direct:second") .end() - .log(LoggingLevel.INFO, "test","RECEIVED response \${body}") + .log(LoggingLevel.INFO, "test", "RECEIVED response \${body}") } } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestCamelTest.groovy b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestCamelTest.groovy index c0b35c0938..4134e98309 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestCamelTest.groovy +++ b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestCamelTest.groovy @@ -10,9 +10,9 @@ import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.api.trace.Span.Kind.SERVER import com.google.common.collect.ImmutableMap +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.apache.camel.CamelContext import org.apache.camel.ProducerTemplate import org.springframework.boot.SpringApplication diff --git a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestConfig.groovy b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestConfig.groovy index 3e381b8fb3..0a95cf9921 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestConfig.groovy +++ b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/RestConfig.groovy @@ -37,9 +37,9 @@ class RestConfig { // producer - client route from("direct:start") - .log(LoggingLevel.INFO, "test","SENDING request") + .log(LoggingLevel.INFO, "test", "SENDING request") .to("rest:get:api/{module}/unit/{unitId}") - .log(LoggingLevel.INFO, "test","RECEIVED response: '\${body}'") + .log(LoggingLevel.INFO, "test", "RECEIVED response: '\${body}'") } } } diff --git a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/SingleServiceCamelTest.groovy b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/SingleServiceCamelTest.groovy index 0f67ee172c..8d1c16419c 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/SingleServiceCamelTest.groovy +++ b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/SingleServiceCamelTest.groovy @@ -8,10 +8,10 @@ package test import static io.opentelemetry.api.trace.Span.Kind.SERVER import com.google.common.collect.ImmutableMap +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.OkHttpUtils import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import okhttp3.FormBody import okhttp3.HttpUrl import okhttp3.OkHttpClient diff --git a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy index 2888df8a28..1134691278 100644 --- a/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy +++ b/instrumentation/apache-camel-2.20/javaagent/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy @@ -10,9 +10,9 @@ import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.api.trace.Span.Kind.SERVER import com.google.common.collect.ImmutableMap +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.apache.camel.CamelContext import org.apache.camel.ProducerTemplate import org.apache.camel.builder.RouteBuilder diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveSpanManager.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveSpanManager.java deleted file mode 100644 index ed80d8e321..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ActiveSpanManager.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import org.apache.camel.Exchange; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Utility class for managing active spans as a stack associated with an exchange. */ -class ActiveSpanManager { - - private static final String ACTIVE_SPAN_PROPERTY = "OpenTelemetry.activeSpan"; - - private static final Logger LOG = LoggerFactory.getLogger(ActiveSpanManager.class); - - private ActiveSpanManager() {} - - public static Span getSpan(Exchange exchange) { - SpanWithScope spanWithScope = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class); - if (spanWithScope != null) { - return spanWithScope.getSpan(); - } - return null; - } - - /** - * This method activates the supplied span for the supplied exchange. If an existing span is found - * for the exchange, this will be pushed onto a stack. - * - * @param exchange The exchange - * @param span The span - */ - public static void activate(Exchange exchange, Span span) { - - SpanWithScope parent = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class); - SpanWithScope spanWithScope = SpanWithScope.activate(span, parent); - exchange.setProperty(ACTIVE_SPAN_PROPERTY, spanWithScope); - if (LOG.isTraceEnabled()) { - LOG.trace("Activated a span: " + spanWithScope); - } - } - - /** - * This method deactivates an existing active span associated with the supplied exchange. Once - * deactivated, if a parent span is found associated with the stack for the exchange, it will be - * restored as the current span for that exchange. - * - * @param exchange The exchange - */ - public static void deactivate(Exchange exchange) { - - SpanWithScope spanWithScope = exchange.getProperty(ACTIVE_SPAN_PROPERTY, SpanWithScope.class); - - if (spanWithScope != null) { - spanWithScope.deactivate(); - exchange.setProperty(ACTIVE_SPAN_PROPERTY, spanWithScope.getParent()); - if (LOG.isTraceEnabled()) { - LOG.trace("Deactivated span: " + spanWithScope); - } - } - } - - public static class SpanWithScope { - @Nullable private final SpanWithScope parent; - private final Span span; - private final Scope scope; - - public SpanWithScope(SpanWithScope parent, Span span, Scope scope) { - this.parent = parent; - this.span = span; - this.scope = scope; - } - - public static SpanWithScope activate(Span span, SpanWithScope parent) { - Scope scope = CamelTracer.TRACER.startScope(span); - return new SpanWithScope(parent, span, scope); - } - - public SpanWithScope getParent() { - return parent; - } - - public Span getSpan() { - return span; - } - - public void deactivate() { - span.end(); - scope.close(); - } - - @Override - public String toString() { - return "SpanWithScope [span=" + span + ", scope=" + scope + "]"; - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ApacheCamelInstrumentationModule.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ApacheCamelInstrumentationModule.java deleted file mode 100644 index 2d7f6137b6..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/ApacheCamelInstrumentationModule.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.camel.CamelContext; - -@AutoService(InstrumentationModule.class) -public class ApacheCamelInstrumentationModule extends InstrumentationModule { - - public ApacheCamelInstrumentationModule() { - super("apache-camel", "apache-camel-2.20"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new CamelContextInstrumentation()); - } - - public static class CamelContextInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.apache.camel.CamelContext"); - } - - @Override - public ElementMatcher typeMatcher() { - return not(isAbstract()).and(implementsInterface(named("org.apache.camel.CamelContext"))); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - named("start").and(isPublic()).and(takesArguments(0)), - ApacheCamelInstrumentationModule.class.getName() + "$ContextAdvice"); - } - } - - public static class ContextAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onContextStart(@Advice.This final CamelContext context) throws Exception { - - if (context.hasService(CamelTracingService.class) == null) { - // start this service eager so we init before Camel is starting up - context.addService(new CamelTracingService(context), true, true); - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelDirection.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelDirection.java deleted file mode 100644 index a18b1777dc..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelDirection.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -public enum CamelDirection { - INBOUND, - OUTBOUND; -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java deleted file mode 100644 index 668756d501..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelEventNotifier.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import java.util.EventObject; -import org.apache.camel.management.event.ExchangeSendingEvent; -import org.apache.camel.management.event.ExchangeSentEvent; -import org.apache.camel.support.EventNotifierSupport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class CamelEventNotifier extends EventNotifierSupport { - - private static final Logger LOG = LoggerFactory.getLogger(CamelEventNotifier.class); - - @Override - public void notify(EventObject event) { - - try { - if (event instanceof ExchangeSendingEvent) { - onExchangeSending((ExchangeSendingEvent) event); - } else if (event instanceof ExchangeSentEvent) { - onExchangeSent((ExchangeSentEvent) event); - } - } catch (Throwable t) { - LOG.warn("Failed to capture tracing data", t); - } - } - - /** Camel about to send (outbound). */ - private void onExchangeSending(ExchangeSendingEvent ese) { - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(ese.getEndpoint()); - if (!sd.shouldStartNewSpan()) { - return; - } - - String name = - sd.getOperationName(ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND); - Span span = CamelTracer.TRACER.startSpan(name, sd.getInitiatorSpanKind()); - sd.pre(span, ese.getExchange(), ese.getEndpoint(), CamelDirection.OUTBOUND); - CamelPropagationUtil.injectParent(Context.current(), ese.getExchange().getIn().getHeaders()); - ActiveSpanManager.activate(ese.getExchange(), span); - - if (LOG.isTraceEnabled()) { - LOG.trace("[Exchange sending] Initiator span started " + span); - } - } - - /** Camel finished sending (outbound). Finish span and remove it from CAMEL holder. */ - private void onExchangeSent(ExchangeSentEvent event) { - ExchangeSentEvent ese = event; - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(ese.getEndpoint()); - if (!sd.shouldStartNewSpan()) { - return; - } - - Span span = ActiveSpanManager.getSpan(ese.getExchange()); - if (span != null) { - if (LOG.isTraceEnabled()) { - LOG.trace("[Exchange sent] Initiator span finished " + span); - } - sd.post(span, ese.getExchange(), ese.getEndpoint()); - ActiveSpanManager.deactivate(ese.getExchange()); - } else { - LOG.warn("Could not find managed span for exchange " + ese.getExchange()); - } - } - - @Override - public boolean isEnabled(EventObject event) { - return event instanceof ExchangeSendingEvent || event instanceof ExchangeSentEvent; - } - - @Override - public String toString() { - return "OpenTelemetryCamelEventNotifier"; - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelPropagationUtil.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelPropagationUtil.java deleted file mode 100644 index a65c553dde..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelPropagationUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import java.util.Map; - -final class CamelPropagationUtil { - - private CamelPropagationUtil() {} - - static Context extractParent(final Map exchangeHeaders) { - return OpenTelemetry.getGlobalPropagators() - .getTextMapPropagator() - .extract(Context.current(), exchangeHeaders, MapGetter.INSTANCE); - } - - static void injectParent(Context context, final Map exchangeHeaders) { - OpenTelemetry.getGlobalPropagators() - .getTextMapPropagator() - .inject(context, exchangeHeaders, MapSetter.INSTANCE); - } - - private static class MapGetter implements Getter> { - - private static final MapGetter INSTANCE = new MapGetter(); - - @Override - public Iterable keys(Map map) { - return map.keySet(); - } - - @Override - public String get(Map map, String s) { - return (map.containsKey(s) ? map.get(s).toString() : null); - } - } - - private static class MapSetter implements Setter> { - - private static final MapSetter INSTANCE = new MapSetter(); - - @Override - public void set(Map carrier, String key, String value) { - // Camel keys are internal ones - if (!key.startsWith("Camel")) { - carrier.put(key, value); - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java deleted file mode 100644 index 3870cb2900..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelRoutePolicy.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.context.Context; -import org.apache.camel.Exchange; -import org.apache.camel.Route; -import org.apache.camel.support.RoutePolicySupport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class CamelRoutePolicy extends RoutePolicySupport { - - private static final Logger LOG = LoggerFactory.getLogger(CamelRoutePolicy.class); - - private Span spanOnExchangeBegin(Route route, Exchange exchange, SpanDecorator sd) { - Span activeSpan = CamelTracer.TRACER.getCurrentSpan(); - String name = sd.getOperationName(exchange, route.getEndpoint(), CamelDirection.INBOUND); - SpanBuilder builder = CamelTracer.TRACER.spanBuilder(name); - if (!activeSpan.getSpanContext().isValid()) { - // root operation, set kind, otherwise - INTERNAL - builder.setSpanKind(sd.getReceiverSpanKind()); - Context parentContext = CamelPropagationUtil.extractParent(exchange.getIn().getHeaders()); - if (parentContext != null) { - builder.setParent(parentContext); - } - } - return builder.startSpan(); - } - - /** - * Route exchange started, ie request could have been already captured by upper layer - * instrumentation. - */ - @Override - public void onExchangeBegin(Route route, Exchange exchange) { - try { - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(route.getEndpoint()); - Span span = spanOnExchangeBegin(route, exchange, sd); - sd.pre(span, exchange, route.getEndpoint(), CamelDirection.INBOUND); - ActiveSpanManager.activate(exchange, span); - if (LOG.isTraceEnabled()) { - LOG.trace("[Route start] Receiver span started " + span); - } - } catch (Throwable t) { - LOG.warn("Failed to capture tracing data", t); - } - } - - /** Route exchange done. Get active CAMEL span, finish, remove from CAMEL holder. */ - @Override - public void onExchangeDone(Route route, Exchange exchange) { - try { - Span span = ActiveSpanManager.getSpan(exchange); - if (span != null) { - if (LOG.isTraceEnabled()) { - LOG.trace("[Route finished] Receiver span finished " + span); - } - SpanDecorator sd = CamelTracer.TRACER.getSpanDecorator(route.getEndpoint()); - sd.post(span, exchange, route.getEndpoint()); - ActiveSpanManager.deactivate(exchange); - } else { - LOG.warn("Could not find managed span for exchange=" + exchange); - } - } catch (Throwable t) { - LOG.warn("Failed to capture tracing data", t); - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracer.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracer.java deleted file mode 100644 index 37dd9b0578..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.apachecamel.decorators.DecoratorRegistry; -import org.apache.camel.Endpoint; -import org.apache.camel.util.StringHelper; - -class CamelTracer extends BaseTracer { - - public static final CamelTracer TRACER = new CamelTracer(); - - private final DecoratorRegistry registry = new DecoratorRegistry(); - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.apache-camel"; - } - - public SpanBuilder spanBuilder(String name) { - return tracer.spanBuilder(name); - } - - public SpanDecorator getSpanDecorator(Endpoint endpoint) { - - String component = ""; - String uri = endpoint.getEndpointUri(); - String[] splitUri = StringHelper.splitOnCharacter(uri, ":", 2); - if (splitUri[1] != null) { - component = splitUri[0]; - } - return registry.forComponent(component); - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracingService.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracingService.java deleted file mode 100644 index 0bbbbe1651..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/CamelTracingService.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import org.apache.camel.CamelContext; -import org.apache.camel.StaticService; -import org.apache.camel.model.RouteDefinition; -import org.apache.camel.spi.RoutePolicy; -import org.apache.camel.spi.RoutePolicyFactory; -import org.apache.camel.support.ServiceSupport; -import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.ServiceHelper; - -public class CamelTracingService extends ServiceSupport - implements RoutePolicyFactory, StaticService { - - private final CamelContext camelContext; - private final CamelEventNotifier eventNotifier = new CamelEventNotifier(); - private final CamelRoutePolicy routePolicy = new CamelRoutePolicy(); - - public CamelTracingService(CamelContext camelContext) { - ObjectHelper.notNull(camelContext, "CamelContext", this); - this.camelContext = camelContext; - } - - @Override - protected void doStart() throws Exception { - camelContext.getManagementStrategy().addEventNotifier(eventNotifier); - if (!camelContext.getRoutePolicyFactories().contains(this)) { - camelContext.addRoutePolicyFactory(this); - } - - ServiceHelper.startServices(eventNotifier); - } - - @Override - protected void doStop() throws Exception { - // stop event notifier - camelContext.getManagementStrategy().removeEventNotifier(eventNotifier); - ServiceHelper.stopService(eventNotifier); - - // remove route policy - camelContext.getRoutePolicyFactories().remove(this); - } - - @Override - public RoutePolicy createRoutePolicy( - CamelContext camelContext, String routeId, RouteDefinition route) { - return routePolicy; - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java deleted file mode 100644 index 6ea3b751b5..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/SpanDecorator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel; - -import io.opentelemetry.api.trace.Span; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; - -/** This interface represents a decorator specific to the component/endpoint being instrumented. */ -public interface SpanDecorator { - - /** - * This method indicates whether the component associated with the SpanDecorator should result in - * a new span being created. - * - * @return Whether a new span should be created - */ - boolean shouldStartNewSpan(); - - /** - * Returns the operation name to use with the Span representing this exchange and endpoint. - * - * @param exchange The exchange - * @param endpoint The endpoint - * @return The operation name - */ - String getOperationName(Exchange exchange, Endpoint endpoint, CamelDirection camelDirection); - - /** - * This method adds appropriate details (tags/logs) to the supplied span based on the pre - * processing of the exchange. - * - * @param span The span - * @param exchange The exchange - * @param endpoint The endpoint - */ - void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection); - - /** - * This method adds appropriate details (tags/logs) to the supplied span based on the post - * processing of the exchange. - * - * @param span The span - * @param exchange The exchange - * @param endpoint The endpoint - */ - void post(Span span, Exchange exchange, Endpoint endpoint); - - /** Returns the 'span.kind' value for use when the component is initiating a communication. */ - Span.Kind getInitiatorSpanKind(); - - /** Returns the 'span.kind' value for use when the component is receiving a communication. */ - Span.Kind getReceiverSpanKind(); -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java deleted file mode 100644 index 701cebd890..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import io.opentelemetry.javaagent.instrumentation.apachecamel.SpanDecorator; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; -import org.apache.camel.util.StringHelper; -import org.apache.camel.util.URISupport; - -/** An abstract base implementation of the {@link SpanDecorator} interface. */ -class BaseSpanDecorator implements SpanDecorator { - - static final String DEFAULT_OPERATION_NAME = "CamelOperation"; - - /** - * This method removes the scheme, any leading slash characters and options from the supplied URI. - * This is intended to extract a meaningful name from the URI that can be used in situations, such - * as the operation name. - * - * @param endpoint The endpoint - * @return The stripped value from the URI - */ - public static String stripSchemeAndOptions(Endpoint endpoint) { - int start = endpoint.getEndpointUri().indexOf(':'); - start++; - // Remove any leading '/' - while (endpoint.getEndpointUri().charAt(start) == '/') { - start++; - } - int end = endpoint.getEndpointUri().indexOf('?'); - return end == -1 - ? endpoint.getEndpointUri().substring(start) - : endpoint.getEndpointUri().substring(start, end); - } - - public static Map toQueryParameters(String uri) { - int index = uri.indexOf('?'); - if (index != -1) { - String queryString = uri.substring(index + 1); - Map map = new HashMap<>(); - for (String param : queryString.split("&")) { - String[] parts = param.split("="); - if (parts.length == 2) { - map.put(parts[0], parts[1]); - } - } - return map; - } - return Collections.emptyMap(); - } - - @Override - public boolean shouldStartNewSpan() { - return true; - } - - @Override - public String getOperationName( - Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - String[] splitUri = StringHelper.splitOnCharacter(endpoint.getEndpointUri(), ":", 2); - return (splitUri.length > 0 ? splitUri[0] : DEFAULT_OPERATION_NAME); - } - - @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - span.setAttribute("camel.uri", URISupport.sanitizeUri(endpoint.getEndpointUri())); - } - - @Override - public void post(Span span, Exchange exchange, Endpoint endpoint) { - if (exchange.isFailed()) { - span.setStatus(StatusCode.ERROR); - if (exchange.getException() != null) { - span.recordException(exchange.getException()); - } - } - } - - @Override - public Span.Kind getInitiatorSpanKind() { - return Kind.CLIENT; - } - - @Override - public Span.Kind getReceiverSpanKind() { - return Kind.SERVER; - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java deleted file mode 100644 index 51c4a5a23f..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import java.net.URI; -import java.util.Map; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; - -class DbSpanDecorator extends BaseSpanDecorator { - - private final String component; - private final String system; - - DbSpanDecorator(String component, String system) { - this.component = component; - this.system = system; - } - - @Override - public String getOperationName( - Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - - switch (component) { - case "mongodb": - case "elasticsearch": - Map queryParameters = toQueryParameters(endpoint.getEndpointUri()); - if (queryParameters.containsKey("operation")) { - return queryParameters.get("operation"); - } - return super.getOperationName(exchange, endpoint, camelDirection); - default: - return super.getOperationName(exchange, endpoint, camelDirection); - } - } - - private String getStatement(Exchange exchange, Endpoint endpoint) { - switch (component) { - case "mongodb": - Map mongoParameters = toQueryParameters(endpoint.getEndpointUri()); - return mongoParameters.toString(); - case "cql": - Object cqlObj = exchange.getIn().getHeader("CamelCqlQuery"); - if (cqlObj != null) { - return cqlObj.toString(); - } - Map cqlParameters = toQueryParameters(endpoint.getEndpointUri()); - if (cqlParameters.containsKey("cql")) { - return cqlParameters.get("cql"); - } - return null; - case "jdbc": - Object body = exchange.getIn().getBody(); - if (body instanceof String) { - return (String) body; - } - return null; - case "sql": - Object sqlquery = exchange.getIn().getHeader("CamelSqlQuery"); - if (sqlquery instanceof String) { - return (String) sqlquery; - } - return null; - default: - return null; - } - } - - private String getDbName(Endpoint endpoint) { - switch (component) { - case "mongodb": - Map mongoParameters = toQueryParameters(endpoint.getEndpointUri()); - return mongoParameters.get("database"); - case "cql": - URI uri = URI.create(endpoint.getEndpointUri()); - if (uri.getPath() != null && uri.getPath().length() > 0) { - // Strip leading '/' from path - return uri.getPath().substring(1); - } - return null; - case "elasticsearch": - Map elasticsearchParameters = toQueryParameters(endpoint.getEndpointUri()); - if (elasticsearchParameters.containsKey("indexName")) { - return elasticsearchParameters.get("indexName"); - } - return null; - default: - return null; - } - } - - @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); - - span.setAttribute(SemanticAttributes.DB_SYSTEM, system); - String statement = getStatement(exchange, endpoint); - if (statement != null) { - span.setAttribute(SemanticAttributes.DB_STATEMENT, statement); - } - String dbName = getDbName(endpoint); - if (dbName != null) { - span.setAttribute(SemanticAttributes.DB_NAME, dbName); - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DecoratorRegistry.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DecoratorRegistry.java deleted file mode 100644 index 69d0e0a90b..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DecoratorRegistry.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.javaagent.instrumentation.apachecamel.SpanDecorator; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.util.HashMap; -import java.util.Map; - -public class DecoratorRegistry { - - private static final SpanDecorator DEFAULT = new BaseSpanDecorator(); - private static final Map DECORATORS = loadDecorators(); - - private static Map loadDecorators() { - - Map result = new HashMap<>(); - result.put("ahc", new HttpSpanDecorator()); - result.put("ampq", new MessagingSpanDecorator("ampq")); - result.put("aws-sns", new MessagingSpanDecorator("aws-sns")); - result.put("aws-sqs", new MessagingSpanDecorator("aws-sqs")); - result.put("cometd", new MessagingSpanDecorator("cometd")); - result.put("cometds", new MessagingSpanDecorator("cometds")); - result.put("cql", new DbSpanDecorator("cql", DbSystem.CASSANDRA)); - result.put("direct", new InternalSpanDecorator()); - result.put("direct-vm", new InternalSpanDecorator()); - result.put("disruptor", new InternalSpanDecorator()); - result.put("disruptor-vm", new InternalSpanDecorator()); - result.put("elasticsearch", new DbSpanDecorator("elasticsearch", "elasticsearch")); - result.put("http4", new HttpSpanDecorator()); - result.put("http", new HttpSpanDecorator()); - result.put("ironmq", new MessagingSpanDecorator("ironmq")); - result.put("jdbc", new DbSpanDecorator("jdbc", DbSystem.OTHER_SQL)); - result.put("jetty", new HttpSpanDecorator()); - result.put("jms", new MessagingSpanDecorator("jms")); - result.put("kafka", new KafkaSpanDecorator()); - result.put("log", new LogSpanDecorator()); - result.put("mongodb", new DbSpanDecorator("mongodb", DbSystem.MONGODB)); - result.put("mqtt", new MessagingSpanDecorator("mqtt")); - result.put("netty-http4", new HttpSpanDecorator()); - result.put("netty-http", new HttpSpanDecorator()); - result.put("paho", new MessagingSpanDecorator("paho")); - result.put("rabbitmq", new MessagingSpanDecorator("rabbitmq")); - result.put("restlet", new HttpSpanDecorator()); - result.put("rest", new RestSpanDecorator()); - result.put("seda", new InternalSpanDecorator()); - result.put("servlet", new HttpSpanDecorator()); - result.put("sjms", new MessagingSpanDecorator("sjms")); - result.put("sql", new DbSpanDecorator("sql", DbSystem.OTHER_SQL)); - result.put("stomp", new MessagingSpanDecorator("stomp")); - result.put("timer", new TimerSpanDecorator()); - result.put("undertow", new HttpSpanDecorator()); - result.put("vm", new InternalSpanDecorator()); - return result; - } - - public SpanDecorator forComponent(final String component) { - - return DECORATORS.getOrDefault(component, DEFAULT); - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java deleted file mode 100644 index 58cd91ba14..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import java.net.MalformedURLException; -import java.net.URL; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; -import org.checkerframework.checker.nullness.qual.Nullable; - -class HttpSpanDecorator extends BaseSpanDecorator { - - private static final String POST_METHOD = "POST"; - private static final String GET_METHOD = "GET"; - - protected static String getHttpMethod(Exchange exchange, Endpoint endpoint) { - // 1. Use method provided in header. - Object method = exchange.getIn().getHeader(Exchange.HTTP_METHOD); - if (method instanceof String) { - return (String) method; - } - - // 2. GET if query string is provided in header. - if (exchange.getIn().getHeader(Exchange.HTTP_QUERY) != null) { - return GET_METHOD; - } - - // 3. GET if endpoint is configured with a query string. - if (endpoint.getEndpointUri().indexOf('?') != -1) { - return GET_METHOD; - } - - // 4. POST if there is data to send (body is not null). - if (exchange.getIn().getBody() != null) { - return POST_METHOD; - } - - // 5. GET otherwise. - return GET_METHOD; - } - - @Override - public String getOperationName( - Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - // Based on HTTP component documentation: - String spanName = null; - if (shouldSetPathAsName(camelDirection)) { - spanName = getPath(exchange, endpoint); - } - return (spanName == null ? getHttpMethod(exchange, endpoint) : spanName); - } - - @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); - - String httpUrl = getHttpUrl(exchange, endpoint); - if (httpUrl != null) { - span.setAttribute(SemanticAttributes.HTTP_URL, httpUrl); - } - - span.setAttribute(SemanticAttributes.HTTP_METHOD, getHttpMethod(exchange, endpoint)); - - Span serverSpan = Context.current().get(BaseTracer.CONTEXT_SERVER_SPAN_KEY); - if (shouldUpdateServerSpanName(serverSpan, camelDirection)) { - updateServerSpanName(serverSpan, exchange, endpoint); - } - } - - private boolean shouldSetPathAsName(CamelDirection camelDirection) { - return CamelDirection.INBOUND.equals(camelDirection); - } - - @Nullable - protected String getPath(Exchange exchange, Endpoint endpoint) { - - String httpUrl = getHttpUrl(exchange, endpoint); - try { - URL url = new URL(httpUrl); - return url.getPath(); - } catch (MalformedURLException e) { - return null; - } - } - - private boolean shouldUpdateServerSpanName(Span serverSpan, CamelDirection camelDirection) { - return (serverSpan != null && shouldSetPathAsName(camelDirection)); - } - - private void updateServerSpanName(Span serverSpan, Exchange exchange, Endpoint endpoint) { - String path = getPath(exchange, endpoint); - if (path != null) { - serverSpan.updateName(path); - } - } - - protected String getHttpUrl(Exchange exchange, Endpoint endpoint) { - Object url = exchange.getIn().getHeader(Exchange.HTTP_URL); - if (url instanceof String) { - return (String) url; - } else { - Object uri = exchange.getIn().getHeader(Exchange.HTTP_URI); - if (uri instanceof String) { - return (String) uri; - } else { - // Try to obtain from endpoint - int index = endpoint.getEndpointUri().lastIndexOf("http:"); - if (index != -1) { - return endpoint.getEndpointUri().substring(index); - } - } - } - return null; - } - - @Override - public void post(Span span, Exchange exchange, Endpoint endpoint) { - super.post(span, exchange, endpoint); - - if (exchange.hasOut()) { - Object responseCode = exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE); - if (responseCode instanceof Integer) { - span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, (Integer) responseCode); - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/InternalSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/InternalSpanDecorator.java deleted file mode 100644 index 195a458832..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/InternalSpanDecorator.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; - -class InternalSpanDecorator extends BaseSpanDecorator { - - @Override - public String getOperationName( - Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - // Internal communications use descriptive names, so suitable - // as an operation name, but need to strip the scheme and any options - return stripSchemeAndOptions(endpoint); - } - - @Override - public boolean shouldStartNewSpan() { - return false; - } - - @Override - public Kind getReceiverSpanKind() { - return Kind.INTERNAL; - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java deleted file mode 100644 index eba42bba0c..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/KafkaSpanDecorator.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import java.util.Map; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; - -class KafkaSpanDecorator extends MessagingSpanDecorator { - - private static final String PARTITION_KEY = "kafka.PARTITION_KEY"; - private static final String PARTITION = "kafka.PARTITION"; - private static final String KEY = "kafka.KEY"; - private static final String TOPIC = "kafka.TOPIC"; - private static final String OFFSET = "kafka.OFFSET"; - - public KafkaSpanDecorator() { - super("kafka"); - } - - @Override - public String getDestination(Exchange exchange, Endpoint endpoint) { - String topic = (String) exchange.getIn().getHeader(TOPIC); - if (topic == null) { - Map queryParameters = toQueryParameters(endpoint.getEndpointUri()); - topic = queryParameters.get("topic"); - } - return topic != null ? topic : super.getDestination(exchange, endpoint); - } - - @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); - - span.setAttribute(SemanticAttributes.MESSAGING_OPERATION, "process"); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "topic"); - - String partition = getValue(exchange, PARTITION, Integer.class); - if (partition != null) { - span.setAttribute("partition", partition); - } - - String partitionKey = (String) exchange.getIn().getHeader(PARTITION_KEY); - if (partitionKey != null) { - span.setAttribute("partitionKey", partitionKey); - } - - String key = (String) exchange.getIn().getHeader(KEY); - if (key != null) { - span.setAttribute("key", key); - } - - String offset = getValue(exchange, OFFSET, Long.class); - if (offset != null) { - span.setAttribute("offset", offset); - } - } - - /** - * Extracts header value from the exchange for given header. - * - * @param exchange the {@link Exchange} - * @param header the header name - * @param type the class type of the exchange header - */ - private String getValue(final Exchange exchange, final String header, Class type) { - T value = exchange.getIn().getHeader(header, type); - return value != null ? String.valueOf(value) : exchange.getIn().getHeader(header, String.class); - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/LogSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/LogSpanDecorator.java deleted file mode 100644 index ddf60ea6d4..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/LogSpanDecorator.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -class LogSpanDecorator extends BaseSpanDecorator { - - @Override - public boolean shouldStartNewSpan() { - return false; - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java deleted file mode 100644 index e13fa578c0..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/MessagingSpanDecorator.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import java.net.URI; -import java.util.Map; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; - -class MessagingSpanDecorator extends BaseSpanDecorator { - - private final String component; - - public MessagingSpanDecorator(String component) { - this.component = component; - } - - @Override - public String getOperationName( - Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - - if ("mqtt".equals(component)) { - return stripSchemeAndOptions(endpoint); - } - return getDestination(exchange, endpoint); - } - - @Override - public void pre(Span span, Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - super.pre(span, exchange, endpoint, camelDirection); - - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, getDestination(exchange, endpoint)); - - String messageId = getMessageId(exchange); - if (messageId != null) { - span.setAttribute(SemanticAttributes.MESSAGING_MESSAGE_ID, messageId); - } - } - - /** - * This method identifies the destination from the supplied exchange and/or endpoint. - * - * @param exchange The exchange - * @param endpoint The endpoint - * @return The message bus destination - */ - protected String getDestination(Exchange exchange, Endpoint endpoint) { - switch (component) { - case "cometds": - case "cometd": - return URI.create(endpoint.getEndpointUri()).getPath().substring(1); - case "rabbitmq": - return (String) exchange.getIn().getHeader("rabbitmq.EXCHANGE_NAME"); - case "stomp": - String destination = stripSchemeAndOptions(endpoint); - if (destination.startsWith("queue:")) { - destination = destination.substring("queue:".length()); - } - return destination; - case "mqtt": - Map queryParameters = toQueryParameters(endpoint.getEndpointUri()); - return (queryParameters.containsKey("subscribeTopicNames") - ? queryParameters.get("subscribeTopicNames") - : queryParameters.get("publishTopicName")); - default: - return stripSchemeAndOptions(endpoint); - } - } - - @Override - public Span.Kind getInitiatorSpanKind() { - return Kind.PRODUCER; - } - - @Override - public Span.Kind getReceiverSpanKind() { - return Kind.CONSUMER; - } - - /** - * This method identifies the message id for the messaging exchange. - * - * @return The message id, or null if no id exists for the exchange - */ - protected String getMessageId(Exchange exchange) { - switch (component) { - case "aws-sns": - return (String) exchange.getIn().getHeader("CamelAwsSnsMessageId"); - case "aws-sqs": - return (String) exchange.getIn().getHeader("CamelAwsSqsMessageId"); - case "ironmq": - return (String) exchange.getIn().getHeader("CamelIronMQMessageId"); - case "jms": - return (String) exchange.getIn().getHeader("JMSMessageID"); - default: - return null; - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/RestSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/RestSpanDecorator.java deleted file mode 100644 index 8b2f278efe..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/RestSpanDecorator.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class RestSpanDecorator extends HttpSpanDecorator { - - private static final Logger LOG = LoggerFactory.getLogger(RestSpanDecorator.class); - - @Override - protected String getPath(Exchange exchange, Endpoint endpoint) { - String endpointUri = endpoint.getEndpointUri(); - // Obtain the 'path' part of the URI format: rest://method:path[:uriTemplate]?[options] - String path = null; - int index = endpointUri.indexOf(':'); - if (index != -1) { - index = endpointUri.indexOf(':', index + 1); - if (index != -1) { - path = endpointUri.substring(index + 1); - index = path.indexOf('?'); - if (index != -1) { - path = path.substring(0, index); - } - path = path.replaceAll(":", ""); - try { - path = URLDecoder.decode(path, "UTF-8"); - } catch (UnsupportedEncodingException e) { - LOG.debug("Failed to decode URL path '" + path + "', ignoring exception", e); - } - } - } - return path; - } -} diff --git a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/TimerSpanDecorator.java b/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/TimerSpanDecorator.java deleted file mode 100644 index 402fbb7d61..0000000000 --- a/instrumentation/apache-camel-2.20/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/TimerSpanDecorator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -// Includes work from: -/* - * Apache Camel Opentracing Component - * - * Licensed to the Apache Software Foundation (ASF) under one or more contributor license - * agreements. See the NOTICE file distributed with this work for additional information regarding - * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. You may obtain a - * copy of the License at - * - *

http://www.apache.org/licenses/LICENSE-2.0 - * - *

Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators; - -import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; - -class TimerSpanDecorator extends BaseSpanDecorator { - - @Override - public String getOperationName( - Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) { - Object name = exchange.getProperty(Exchange.TIMER_NAME); - if (name instanceof String) { - return (String) name; - } - - return super.getOperationName(exchange, endpoint, camelDirection); - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/DirectCamelTest.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/DirectCamelTest.groovy deleted file mode 100644 index 371db0c7ce..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/DirectCamelTest.groovy +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.camel.CamelContext -import org.apache.camel.ProducerTemplate -import org.springframework.boot.SpringApplication -import org.springframework.context.ConfigurableApplicationContext -import spock.lang.Shared - -class DirectCamelTest extends AgentTestRunner { - - @Shared - ConfigurableApplicationContext server - - def setupSpec() { - def app = new SpringApplication(DirectConfig) - server = app.run() - } - - def cleanupSpec() { - if (server != null) { - server.close() - server = null - } - } - - def "simple direct to a single services"() { - setup: - def camelContext = server.getBean(CamelContext) - ProducerTemplate template = camelContext.createProducerTemplate() - - when: - template.sendBody("direct:input", "Example request") - - then: - assertTraces(1) { - trace(0, 2) { - def parent = it - it.span(0) { - name "input" - kind INTERNAL - hasNoParent() - attributes { - "camel.uri" "direct://input" - } - } - it.span(1) { - name "receiver" - kind INTERNAL - parentSpanId parent.span(0).spanId - attributes { - "camel.uri" "direct://receiver" - } - } - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/DirectConfig.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/DirectConfig.groovy deleted file mode 100644 index d0b3d22c2d..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/DirectConfig.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import org.apache.camel.LoggingLevel -import org.apache.camel.builder.RouteBuilder -import org.springframework.boot.SpringBootConfiguration -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean - -@SpringBootConfiguration -@EnableAutoConfiguration -class DirectConfig { - - @Bean - RouteBuilder receiverRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - from("direct:receiver") - .log(LoggingLevel.INFO, "test", "RECEIVER got: \${body}") - .delay(simple("2000")) - .setBody(constant("result")) - } - } - } - - @Bean - RouteBuilder clientRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - from("direct:input") - .log(LoggingLevel.INFO, "test", "SENDING request \${body}") - .to("direct:receiver") - .log(LoggingLevel.INFO, "test", "RECEIVED response \${body}") - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/MulticastConfig.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/MulticastConfig.groovy deleted file mode 100644 index 6fdd74d687..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/MulticastConfig.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import org.apache.camel.LoggingLevel -import org.apache.camel.builder.RouteBuilder -import org.springframework.boot.SpringBootConfiguration -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean - -@SpringBootConfiguration -@EnableAutoConfiguration -class MulticastConfig { - - @Bean - RouteBuilder firstServiceRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - from("direct:first") - .log(LoggingLevel.INFO, "test", "FIRST request: \${body}") - .delay(simple("1000")) - .setBody(constant("first")) - } - } - } - - @Bean - RouteBuilder secondServiceRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - from("direct:second") - .log(LoggingLevel.INFO, "test", "SECOND request: \${body}") - .delay(simple("2000")) - .setBody(constant("second")) - } - } - } - - @Bean - RouteBuilder clientServiceRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - from("direct:input") - .log(LoggingLevel.INFO, "test", "SENDING request \${body}") - .multicast() - .parallelProcessing() - .to("direct:first", "direct:second") - .end() - .log(LoggingLevel.INFO, "test", "RECEIVED response \${body}") - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/MulticastDirectCamelTest.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/MulticastDirectCamelTest.groovy deleted file mode 100644 index 1e2b555394..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/MulticastDirectCamelTest.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.camel.CamelContext -import org.apache.camel.ProducerTemplate -import org.springframework.boot.SpringApplication -import org.springframework.context.ConfigurableApplicationContext -import spock.lang.Shared - -class MulticastDirectCamelTest extends AgentTestRunner { - - @Shared - ConfigurableApplicationContext server - - def setupSpec() { - def app = new SpringApplication(MulticastConfig) - server = app.run() - } - - def cleanupSpec() { - if (server != null) { - server.close() - server = null - } - } - - def "parallel multicast to two child services"() { - setup: - def camelContext = server.getBean(CamelContext) - ProducerTemplate template = camelContext.createProducerTemplate() - - when: - template.sendBody("direct:input", "Example request") - - then: - assertTraces(1) { - trace(0, 3) { - def parent = it - it.span(0) { - name "input" - kind INTERNAL - hasNoParent() - attributes { - "camel.uri" "direct://input" - } - } - it.span(1) { - name "second" - kind INTERNAL - parentSpanId parent.span(0).spanId - attributes { - "camel.uri" "direct://second" - } - } - it.span(2) { - name "first" - kind INTERNAL - parentSpanId parent.span(0).spanId - attributes { - "camel.uri" "direct://first" - } - } - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/RestCamelTest.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/RestCamelTest.groovy deleted file mode 100644 index 4134e98309..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/RestCamelTest.groovy +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.api.trace.Span.Kind.SERVER - -import com.google.common.collect.ImmutableMap -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import org.apache.camel.CamelContext -import org.apache.camel.ProducerTemplate -import org.springframework.boot.SpringApplication -import org.springframework.context.ConfigurableApplicationContext -import spock.lang.Shared - -class RestCamelTest extends AgentTestRunner { - - @Shared - ConfigurableApplicationContext server - @Shared - int port - - def setupSpec() { - withRetryOnAddressAlreadyInUse({ - setupSpecUnderRetry() - }) - } - - def setupSpecUnderRetry() { - port = PortUtils.randomOpenPort() - def app = new SpringApplication(RestConfig) - app.setDefaultProperties(ImmutableMap.of("restServer.port", port)) - server = app.run() - println getClass().name + " http server started at: http://localhost:$port/" - } - - def cleanupSpec() { - if (server != null) { - server.close() - server = null - } - } - - def "rest component - server and client call with jetty backend"() { - setup: - def camelContext = server.getBean(CamelContext) - ProducerTemplate template = camelContext.createProducerTemplate() - - when: - // run client and server in separate threads to simulate "real" rest client/server call - new Thread(new Runnable() { - @Override - void run() { - template.sendBodyAndHeaders("direct:start", null, ImmutableMap.of("module", "firstModule", "unitId", "unitOne")) - } - } - ).start() - - then: - assertTraces(1) { - trace(0, 5) { - it.span(0) { - name "start" - kind INTERNAL - attributes { - "camel.uri" "direct://start" - } - } - it.span(1) { - name "GET" - kind CLIENT - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "GET" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "camel.uri" "rest://get:api/%7Bmodule%7D/unit/%7BunitId%7D" - } - } - it.span(2) { - name "/api/{module}/unit/{unitId}" - kind SERVER - attributes { - "$SemanticAttributes.HTTP_URL.key" "http://localhost:$port/api/firstModule/unit/unitOne" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "$SemanticAttributes.HTTP_CLIENT_IP.key" "127.0.0.1" - "$SemanticAttributes.HTTP_USER_AGENT.key" String - "$SemanticAttributes.HTTP_FLAVOR.key" "HTTP/1.1" - "$SemanticAttributes.HTTP_METHOD.key" "GET" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_PORT.key" Long - } - } - it.span(3) { - name "/api/{module}/unit/{unitId}" - kind INTERNAL - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "GET" - "$SemanticAttributes.HTTP_URL.key" "http://localhost:$port/api/firstModule/unit/unitOne" - "camel.uri" String - } - } - it.span(4) { - name "moduleUnit" - kind INTERNAL - attributes { - "camel.uri" "direct://moduleUnit" - } - } - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/RestConfig.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/RestConfig.groovy deleted file mode 100644 index 0a95cf9921..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/RestConfig.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import org.apache.camel.LoggingLevel -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.model.rest.RestBindingMode -import org.springframework.boot.SpringBootConfiguration -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean - -@SpringBootConfiguration -@EnableAutoConfiguration -class RestConfig { - - @Bean - RouteBuilder routes() { - return new RouteBuilder() { - @Override - void configure() throws Exception { - - restConfiguration() - .component("jetty") - .bindingMode(RestBindingMode.auto) - .host("localhost") - .port("{{restServer.port}}") - - rest("/api") - .get("/{module}/unit/{unitId}") - .to("direct:moduleUnit") - - from("direct:moduleUnit") - .transform().simple("\${header.unitId} of \${header.module}") - - // producer - client route - from("direct:start") - .log(LoggingLevel.INFO, "test", "SENDING request") - .to("rest:get:api/{module}/unit/{unitId}") - .log(LoggingLevel.INFO, "test", "RECEIVED response: '\${body}'") - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/SingleServiceCamelTest.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/SingleServiceCamelTest.groovy deleted file mode 100644 index 8d1c16419c..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/SingleServiceCamelTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import static io.opentelemetry.api.trace.Span.Kind.SERVER - -import com.google.common.collect.ImmutableMap -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.OkHttpUtils -import io.opentelemetry.instrumentation.test.utils.PortUtils -import okhttp3.FormBody -import okhttp3.HttpUrl -import okhttp3.OkHttpClient -import okhttp3.Request -import org.springframework.boot.SpringApplication -import org.springframework.context.ConfigurableApplicationContext -import spock.lang.Shared - -class SingleServiceCamelTest extends AgentTestRunner { - - @Shared - ConfigurableApplicationContext server - @Shared - OkHttpClient client = OkHttpUtils.client() - @Shared - int port - @Shared - URI address - - def setupSpec() { - withRetryOnAddressAlreadyInUse({ - setupSpecUnderRetry() - }) - } - - def setupSpecUnderRetry() { - port = PortUtils.randomOpenPort() - address = new URI("http://localhost:$port/") - def app = new SpringApplication(SingleServiceConfig) - app.setDefaultProperties(ImmutableMap.of("camelService.port", port)) - server = app.run() - println getClass().name + " http server started at: http://localhost:$port/" - } - - def cleanupSpec() { - if (server != null) { - server.close() - server = null - } - } - - def "single camel service span"() { - setup: - def requestUrl = address.resolve("/camelService") - def url = HttpUrl.get(requestUrl) - def request = new Request.Builder() - .url(url) - .method("POST", - new FormBody.Builder().add("", "testContent").build()) - .build() - - when: - client.newCall(request).execute() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - kind SERVER - name "/camelService" - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "${address.resolve("/camelService")}" - "camel.uri" "${address.resolve("/camelService")}".replace("localhost", "0.0.0.0") - } - } - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/SingleServiceConfig.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/SingleServiceConfig.groovy deleted file mode 100644 index 97f7386c24..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/SingleServiceConfig.groovy +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import org.apache.camel.LoggingLevel -import org.apache.camel.builder.RouteBuilder -import org.springframework.boot.SpringBootConfiguration -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean - -@SpringBootConfiguration -@EnableAutoConfiguration -class SingleServiceConfig { - - @Bean - RouteBuilder serviceRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - - from("undertow:http://0.0.0.0:{{camelService.port}}/camelService") - .routeId("camelService") - .streamCaching() - .log("CamelService request: \${body}") - .delay(simple("\${random(1000, 2000)}")) - .transform(simple("CamelService-\${body}")) - .log(LoggingLevel.INFO, "test", "CamelService response: \${body}") - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/TwoServicesConfig.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/TwoServicesConfig.groovy deleted file mode 100644 index 67f706ca57..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/TwoServicesConfig.groovy +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import org.apache.camel.builder.RouteBuilder -import org.springframework.boot.SpringBootConfiguration -import org.springframework.boot.autoconfigure.EnableAutoConfiguration -import org.springframework.context.annotation.Bean - -@SpringBootConfiguration -@EnableAutoConfiguration -class TwoServicesConfig { - - @Bean - RouteBuilder serviceOneRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - - from("undertow:http://0.0.0.0:{{service.one.port}}/serviceOne") - .routeId("serviceOne") - .streamCaching() - .removeHeaders("CamelHttp*") - .log("Service One request: \${body}") - .delay(simple("\${random(1000,2000)}")) - .transform(simple("Service-One-\${body}")) - .to("http://0.0.0.0:{{service.two.port}}/serviceTwo") - .log("Service One response: \${body}") - } - } - } - - @Bean - RouteBuilder serviceTwoRoute() { - return new RouteBuilder() { - - @Override - void configure() throws Exception { - - from("jetty:http://0.0.0.0:{{service.two.port}}/serviceTwo?arg=value") - .routeId("serviceTwo") - .streamCaching() - .log("Service Two request: \${body}") - .delay(simple("\${random(1000, 2000)}")) - .transform(simple("Service-Two-\${body}")) - .log("Service Two response: \${body}") - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy b/instrumentation/apache-camel-2.20/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy deleted file mode 100644 index 1134691278..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/groovy/test/TwoServicesWithDirectClientCamelTest.groovy +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.api.trace.Span.Kind.SERVER - -import com.google.common.collect.ImmutableMap -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import org.apache.camel.CamelContext -import org.apache.camel.ProducerTemplate -import org.apache.camel.builder.RouteBuilder -import org.apache.camel.impl.DefaultCamelContext -import org.springframework.boot.SpringApplication -import org.springframework.context.ConfigurableApplicationContext -import spock.lang.Shared - -class TwoServicesWithDirectClientCamelTest extends AgentTestRunner { - - @Shared - int portOne - @Shared - int portTwo - @Shared - ConfigurableApplicationContext server - @Shared - CamelContext clientContext - - def setupSpec() { - withRetryOnAddressAlreadyInUse({ - setupSpecUnderRetry() - }) - } - - def setupSpecUnderRetry() { - portOne = PortUtils.randomOpenPort() - portTwo = PortUtils.randomOpenPort() - def app = new SpringApplication(TwoServicesConfig) - app.setDefaultProperties(ImmutableMap.of("service.one.port", portOne, "service.two.port", portTwo)) - server = app.run() - } - - def createAndStartClient() { - clientContext = new DefaultCamelContext() - clientContext.addRoutes(new RouteBuilder() { - void configure() { - from("direct:input") - .log("SENT Client request") - .to("http://localhost:$portOne/serviceOne") - .log("RECEIVED Client response") - } - }) - clientContext.start() - } - - def cleanupSpec() { - if (server != null) { - server.close() - server = null - } - } - - def "two camel service spans"() { - setup: - createAndStartClient() - ProducerTemplate template = clientContext.createProducerTemplate() - - when: - template.sendBody("direct:input", "Example request") - - then: - assertTraces(1) { - trace(0, 8) { - it.span(0) { - name "input" - kind INTERNAL - attributes { - "camel.uri" "direct://input" - } - } - it.span(1) { - name "POST" - kind CLIENT - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "http://localhost:$portOne/serviceOne" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "camel.uri" "http://localhost:$portOne/serviceOne" - } - } - it.span(2) { - name "HTTP POST" - kind CLIENT - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "http://localhost:$portOne/serviceOne" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" portOne - "$SemanticAttributes.NET_TRANSPORT.key" "IP.TCP" - "$SemanticAttributes.HTTP_FLAVOR.key" "1.1" - } - } - it.span(3) { - name "/serviceOne" - kind SERVER - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "http://localhost:$portOne/serviceOne" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "camel.uri" "http://0.0.0.0:$portOne/serviceOne" - } - } - it.span(4) { - name "POST" - kind CLIENT - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "http://0.0.0.0:$portTwo/serviceTwo" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "camel.uri" "http://0.0.0.0:$portTwo/serviceTwo" - } - } - it.span(5) { - name "HTTP POST" - kind CLIENT - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "http://0.0.0.0:$portTwo/serviceTwo" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "$SemanticAttributes.NET_PEER_NAME.key" "0.0.0.0" - "$SemanticAttributes.NET_PEER_PORT.key" portTwo - "$SemanticAttributes.NET_TRANSPORT.key" "IP.TCP" - "$SemanticAttributes.HTTP_FLAVOR.key" "1.1" - "$SemanticAttributes.HTTP_USER_AGENT.key" "Jakarta Commons-HttpClient/3.1" - } - } - it.span(6) { - name "/serviceTwo" - kind SERVER - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_STATUS_CODE.key" 200 - "$SemanticAttributes.HTTP_URL.key" "http://0.0.0.0:$portTwo/serviceTwo" - "$SemanticAttributes.NET_PEER_PORT.key" Number - "$SemanticAttributes.NET_PEER_IP.key" InetAddress.getLocalHost().getHostAddress().toString() - "$SemanticAttributes.HTTP_USER_AGENT.key" "Jakarta Commons-HttpClient/3.1" - "$SemanticAttributes.HTTP_FLAVOR.key" "HTTP/1.1" - "$SemanticAttributes.HTTP_CLIENT_IP.key" InetAddress.getLocalHost().getHostAddress().toString() - - } - } - it.span(7) { - name "/serviceTwo" - kind INTERNAL - attributes { - "$SemanticAttributes.HTTP_METHOD.key" "POST" - "$SemanticAttributes.HTTP_URL.key" "http://0.0.0.0:$portTwo/serviceTwo" - "camel.uri" "jetty:http://0.0.0.0:$portTwo/serviceTwo?arg=value" - } - } - } - } - } -} diff --git a/instrumentation/apache-camel-2.20/src/test/resources/logback.xml b/instrumentation/apache-camel-2.20/src/test/resources/logback.xml deleted file mode 100644 index 8aab504caf..0000000000 --- a/instrumentation/apache-camel-2.20/src/test/resources/logback.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - - diff --git a/instrumentation/apache-httpasyncclient-4.0/apache-httpasyncclient-4.0.gradle b/instrumentation/apache-httpasyncclient-4.0/apache-httpasyncclient-4.0.gradle deleted file mode 100644 index fb2fc2bed7..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/apache-httpasyncclient-4.0.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.httpcomponents" - module = "httpasyncclient" - versions = "[4.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.0' -} \ No newline at end of file diff --git a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentation.java b/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentation.java deleted file mode 100644 index 51adb3df62..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentation.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient; - -import static io.opentelemetry.instrumentation.api.tracer.HttpClientTracer.DEFAULT_SPAN_NAME; -import static io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient.ApacheHttpAsyncClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.io.IOException; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.http.HttpException; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.concurrent.FutureCallback; -import org.apache.http.nio.ContentEncoder; -import org.apache.http.nio.IOControl; -import org.apache.http.nio.protocol.HttpAsyncRequestProducer; -import org.apache.http.protocol.HttpContext; -import org.apache.http.protocol.HttpCoreContext; - -public class ApacheHttpAsyncClientInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.apache.http.nio.client.HttpAsyncClient"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.apache.http.nio.client.HttpAsyncClient")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArguments(4)) - .and(takesArgument(0, named("org.apache.http.nio.protocol.HttpAsyncRequestProducer"))) - .and(takesArgument(1, named("org.apache.http.nio.protocol.HttpAsyncResponseConsumer"))) - .and(takesArgument(2, named("org.apache.http.protocol.HttpContext"))) - .and(takesArgument(3, named("org.apache.http.concurrent.FutureCallback"))), - ApacheHttpAsyncClientInstrumentation.class.getName() + "$ClientAdvice"); - } - - public static class ClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Span methodEnter( - @Advice.Argument(value = 0, readOnly = false) HttpAsyncRequestProducer requestProducer, - @Advice.Argument(2) HttpContext context, - @Advice.Argument(value = 3, readOnly = false) FutureCallback futureCallback) { - - Context parentContext = Java8BytecodeBridge.currentContext(); - Span clientSpan = tracer().startSpan(DEFAULT_SPAN_NAME, Kind.CLIENT); - - requestProducer = new DelegatingRequestProducer(clientSpan, requestProducer); - futureCallback = - new TraceContinuedFutureCallback<>(parentContext, clientSpan, context, futureCallback); - - return clientSpan; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Enter Span span, @Advice.Return Object result, @Advice.Thrown Throwable throwable) { - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } - - public static class DelegatingRequestProducer implements HttpAsyncRequestProducer { - Span span; - HttpAsyncRequestProducer delegate; - - public DelegatingRequestProducer(Span span, HttpAsyncRequestProducer delegate) { - this.span = span; - this.delegate = delegate; - } - - @Override - public HttpHost getTarget() { - return delegate.getTarget(); - } - - @Override - public HttpRequest generateRequest() throws IOException, HttpException { - HttpRequest request = delegate.generateRequest(); - span.updateName(tracer().spanNameForRequest(request)); - tracer().onRequest(span, request); - - // TODO (trask) expose inject separate from startScope, e.g. for async cases - Scope scope = tracer().startScope(span, request); - scope.close(); - - return request; - } - - @Override - public void produceContent(ContentEncoder encoder, IOControl ioctrl) throws IOException { - delegate.produceContent(encoder, ioctrl); - } - - @Override - public void requestCompleted(HttpContext context) { - delegate.requestCompleted(context); - } - - @Override - public void failed(Exception ex) { - delegate.failed(ex); - } - - @Override - public boolean isRepeatable() { - return delegate.isRepeatable(); - } - - @Override - public void resetRequest() throws IOException { - delegate.resetRequest(); - } - - @Override - public void close() throws IOException { - delegate.close(); - } - } - - public static class TraceContinuedFutureCallback implements FutureCallback { - private final Context parentContext; - private final Span clientSpan; - private final HttpContext context; - private final FutureCallback delegate; - - public TraceContinuedFutureCallback( - Context parentContext, Span clientSpan, HttpContext context, FutureCallback delegate) { - this.parentContext = parentContext; - this.clientSpan = clientSpan; - this.context = context; - // Note: this can be null in real life, so we have to handle this carefully - this.delegate = delegate; - } - - @Override - public void completed(T result) { - tracer().end(clientSpan, getResponse(context)); - - if (parentContext == null) { - completeDelegate(result); - } else { - try (Scope scope = parentContext.makeCurrent()) { - completeDelegate(result); - } - } - } - - @Override - public void failed(Exception ex) { - // end span before calling delegate - tracer().endExceptionally(clientSpan, getResponse(context), ex); - - if (parentContext == null) { - failDelegate(ex); - } else { - try (Scope scope = parentContext.makeCurrent()) { - failDelegate(ex); - } - } - } - - @Override - public void cancelled() { - // end span before calling delegate - tracer().end(clientSpan, getResponse(context)); - - if (parentContext == null) { - cancelDelegate(); - } else { - try (Scope scope = parentContext.makeCurrent()) { - cancelDelegate(); - } - } - } - - private void completeDelegate(T result) { - if (delegate != null) { - delegate.completed(result); - } - } - - private void failDelegate(Exception ex) { - if (delegate != null) { - delegate.failed(ex); - } - } - - private void cancelDelegate() { - if (delegate != null) { - delegate.cancelled(); - } - } - - private static HttpResponse getResponse(HttpContext context) { - return (HttpResponse) context.getAttribute(HttpCoreContext.HTTP_RESPONSE); - } - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentationModule.java b/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentationModule.java deleted file mode 100644 index 3f3bc668a5..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentationModule.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class ApacheHttpAsyncClientInstrumentationModule extends InstrumentationModule { - public ApacheHttpAsyncClientInstrumentationModule() { - super("apache-httpasyncclient", "apache-httpasyncclient-4.0"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ApacheHttpAsyncClientInstrumentation(), new ApacheHttpClientRedirectInstrumentation()); - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientTracer.java b/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientTracer.java deleted file mode 100644 index 7248aa8102..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientTracer.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient; - -import static io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient.HttpHeadersInjectAdapter.SETTER; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; -import org.apache.http.Header; -import org.apache.http.HttpMessage; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.RequestLine; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpUriRequest; -import org.checkerframework.checker.nullness.qual.Nullable; - -public class ApacheHttpAsyncClientTracer - extends HttpClientTracer { - - private static final ApacheHttpAsyncClientTracer TRACER = new ApacheHttpAsyncClientTracer(); - - public static ApacheHttpAsyncClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequest request) { - if (request instanceof HttpUriRequest) { - return ((HttpUriRequest) request).getMethod(); - } else { - RequestLine requestLine = request.getRequestLine(); - return requestLine == null ? null : requestLine.getMethod(); - } - } - - @Override - protected @Nullable String flavor(HttpRequest httpRequest) { - return httpRequest.getProtocolVersion().toString(); - } - - @Override - protected URI url(HttpRequest request) throws URISyntaxException { - /* - * Note: this is essentially an optimization: HttpUriRequest allows quicker access to required information. - * The downside is that we need to load HttpUriRequest which essentially means we depend on httpasyncclient - * library depending on httpclient library. Currently this seems to be the case. - */ - if (request instanceof HttpUriRequest) { - return ((HttpUriRequest) request).getURI(); - } else { - RequestLine requestLine = request.getRequestLine(); - return requestLine == null ? null : new URI(requestLine.getUri()); - } - } - - @Override - protected Integer status(HttpResponse response) { - StatusLine statusLine = response.getStatusLine(); - return statusLine != null ? statusLine.getStatusCode() : null; - } - - @Override - protected String requestHeader(HttpRequest request, String name) { - return header(request, name); - } - - @Override - protected String responseHeader(HttpResponse response, String name) { - return header(response, name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - private static String header(HttpMessage message, String name) { - Header header = message.getFirstHeader(name); - return header != null ? header.getValue() : null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.apache-httpasyncclient"; - } - - @Override - public String spanNameForRequest(HttpRequest httpRequest) { - return super.spanNameForRequest(httpRequest); - } - - /** This method is overridden to allow other classes in this package to call it. */ - @Override - public Span onRequest(Span span, HttpRequest httpRequest) { - return super.onRequest(span, httpRequest); - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpClientRedirectInstrumentation.java b/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpClientRedirectInstrumentation.java deleted file mode 100644 index 910f503ef0..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpClientRedirectInstrumentation.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.http.Header; -import org.apache.http.HttpRequest; - -/** - * Early versions don't copy headers over on redirect. This instrumentation copies our headers over - * manually. Inspired by - * https://github.com/elastic/apm-agent-java/blob/master/apm-agent-plugins/apm-apache-httpclient-plugin/src/main/java/co/elastic/apm/agent/httpclient/ApacheHttpAsyncClientRedirectInstrumentation.java - */ -public class ApacheHttpClientRedirectInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.apache.http.client.RedirectStrategy"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.apache.http.client.RedirectStrategy")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("getRedirect")) - .and(takesArgument(0, named("org.apache.http.HttpRequest"))), - ApacheHttpClientRedirectInstrumentation.class.getName() + "$ClientRedirectAdvice"); - } - - public static class ClientRedirectAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - private static void onAfterExecute( - @Advice.Argument(0) HttpRequest original, - @Advice.Return(typing = Assigner.Typing.DYNAMIC) HttpRequest redirect) { - if (redirect == null) { - return; - } - // TODO this only handles W3C headers - // Apache HttpClient 4.0.1+ copies headers from original to redirect only - // if redirect headers are empty. Because we add headers - // "traceparent" and "tracestate" to redirect: it means redirect headers never - // will be empty. So in case if not-instrumented redirect had no headers, - // we just copy all not set headers from original to redirect (doing same - // thing as apache httpclient does). - if (!redirect.headerIterator().hasNext()) { - // redirect didn't have other headers besides tracing, so we need to do copy - // (same work as Apache HttpClient 4.0.1+ does w/o instrumentation) - redirect.setHeaders(original.getAllHeaders()); - } else { - for (Header header : original.getAllHeaders()) { - String name = header.getName().toLowerCase(); - if (name.equals("traceparent") || name.equals("tracestate")) { - if (!redirect.containsHeader(header.getName())) { - redirect.setHeader(header.getName(), header.getValue()); - } - } - } - } - } - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/HttpHeadersInjectAdapter.java b/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/HttpHeadersInjectAdapter.java deleted file mode 100644 index 561b8ddbae..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/HttpHeadersInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.apache.http.HttpRequest; - -public class HttpHeadersInjectAdapter implements TextMapPropagator.Setter { - - public static final HttpHeadersInjectAdapter SETTER = new HttpHeadersInjectAdapter(); - - @Override - public void set(HttpRequest carrier, String key, String value) { - carrier.setHeader(key, value); - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientCallbackTest.groovy b/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientCallbackTest.groovy deleted file mode 100644 index 3ecf2a2351..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientCallbackTest.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.CompletableFuture -import org.apache.http.HttpResponse -import org.apache.http.client.config.RequestConfig -import org.apache.http.concurrent.FutureCallback -import org.apache.http.impl.nio.client.HttpAsyncClients -import org.apache.http.message.BasicHeader -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class ApacheHttpAsyncClientCallbackTest extends HttpClientTest { - - @Shared - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(CONNECT_TIMEOUT_MS) - .build() - - @AutoCleanup - @Shared - def client = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build() - - def setupSpec() { - client.start() - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = new HttpUriRequest(method, uri) - headers.entrySet().each { - request.addHeader(new BasicHeader(it.key, it.value)) - } - - def responseFuture = new CompletableFuture<>() - - client.execute(request, new FutureCallback() { - - @Override - void completed(HttpResponse result) { - callback?.call() - responseFuture.complete(result.statusLine.statusCode) - } - - @Override - void failed(Exception ex) { - responseFuture.completeExceptionally(ex) - } - - @Override - void cancelled() { - responseFuture.cancel(true) - } - }) - - return responseFuture.get() - } - - @Override - Integer statusOnRedirectError() { - return 302 - } - - @Override - boolean testRemoteConnection() { - false // otherwise SocketTimeoutException for https requests - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientNullCallbackTest.groovy b/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientNullCallbackTest.groovy deleted file mode 100644 index 6bfba65abe..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientNullCallbackTest.groovy +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.Future -import org.apache.http.client.config.RequestConfig -import org.apache.http.impl.nio.client.HttpAsyncClients -import org.apache.http.message.BasicHeader -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class ApacheHttpAsyncClientNullCallbackTest extends HttpClientTest { - - @Shared - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(CONNECT_TIMEOUT_MS) - .build() - - @AutoCleanup - @Shared - def client = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build() - - def setupSpec() { - client.start() - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = new HttpUriRequest(method, uri) - headers.entrySet().each { - request.addHeader(new BasicHeader(it.key, it.value)) - } - - // The point here is to test case when callback is null - fire-and-forget style - // So to make sure request is done we start request, wait for future to finish - // and then call callback if present. - Future future = client.execute(request, null) - future.get() - if (callback != null) { - callback() - } - return future.get().statusLine.statusCode - } - - @Override - Integer statusOnRedirectError() { - return 302 - } - - @Override - boolean testRemoteConnection() { - false // otherwise SocketTimeoutException for https requests - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientTest.groovy b/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientTest.groovy deleted file mode 100644 index 7e16860d1f..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/ApacheHttpAsyncClientTest.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.CountDownLatch -import org.apache.http.HttpResponse -import org.apache.http.client.config.RequestConfig -import org.apache.http.concurrent.FutureCallback -import org.apache.http.impl.nio.client.HttpAsyncClients -import org.apache.http.message.BasicHeader -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class ApacheHttpAsyncClientTest extends HttpClientTest { - - @Shared - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(CONNECT_TIMEOUT_MS) - .build() - - @AutoCleanup - @Shared - def client = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build() - - def setupSpec() { - client.start() - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = new HttpUriRequest(method, uri) - headers.entrySet().each { - request.addHeader(new BasicHeader(it.key, it.value)) - } - - def latch = new CountDownLatch(callback == null ? 0 : 1) - - def handler = callback == null ? null : new FutureCallback() { - - @Override - void completed(HttpResponse result) { - callback() - latch.countDown() - } - - @Override - void failed(Exception ex) { - latch.countDown() - } - - @Override - void cancelled() { - latch.countDown() - } - } - - def future = client.execute(request, handler) - def response = future.get() - response.entity?.content?.close() // Make sure the connection is closed. - latch.await() - response.statusLine.statusCode - } - - @Override - Integer statusOnRedirectError() { - return 302 - } - - @Override - boolean testRemoteConnection() { - false // otherwise SocketTimeoutException for https requests - } -} diff --git a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/HttpUriRequest.groovy b/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/HttpUriRequest.groovy deleted file mode 100644 index 4a3c7bd57b..0000000000 --- a/instrumentation/apache-httpasyncclient-4.0/src/test/groovy/HttpUriRequest.groovy +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.apache.http.client.methods.HttpRequestBase - -class HttpUriRequest extends HttpRequestBase { - - private final String methodName - - HttpUriRequest(final String methodName, final URI uri) { - this.methodName = methodName - setURI(uri) - } - - @Override - String getMethod() { - return methodName - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-2.0/apache-httpclient-2.0.gradle b/instrumentation/apache-httpclient/apache-httpclient-2.0/apache-httpclient-2.0.gradle deleted file mode 100644 index b1973c2ed8..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-2.0/apache-httpclient-2.0.gradle +++ /dev/null @@ -1,17 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "commons-httpclient" - module = "commons-httpclient" - versions = "[2.0,4.0)" - skipVersions += ["3.1-jenkins-1", "20020423"] // odd versions - assertInverse = true - } -} - -dependencies { - library group: 'commons-httpclient', name: 'commons-httpclient', version: '2.0' - - latestDepTestLibrary group: 'commons-httpclient', name: 'commons-httpclient', version: '3.+' -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientInstrumentationModule.java b/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientInstrumentationModule.java deleted file mode 100644 index 940b2fd800..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientInstrumentationModule.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v2_0.CommonsHttpClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.commons.httpclient.HttpMethod; - -@AutoService(InstrumentationModule.class) -public class ApacheHttpClientInstrumentationModule extends InstrumentationModule { - - public ApacheHttpClientInstrumentationModule() { - super("apache-httpclient", "apache-httpclient-2.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HttpClientInstrumentation()); - } - - public static class HttpClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.apache.commons.httpclient.HttpClient"); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("org.apache.commons.httpclient.HttpClient")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("executeMethod")) - .and(takesArguments(3)) - .and(takesArgument(1, named("org.apache.commons.httpclient.HttpMethod"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$ExecAdvice"); - } - } - - public static class ExecAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(1) HttpMethod httpMethod, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(httpMethod); - if (span.getSpanContext().isValid()) { - scope = tracer().startScope(span, httpMethod); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Argument(1) HttpMethod httpMethod, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable == null) { - tracer().end(span, httpMethod); - } else { - tracer().endExceptionally(span, httpMethod, throwable); - } - } - } - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/CommonsHttpClientTracer.java b/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/CommonsHttpClientTracer.java deleted file mode 100644 index ae91a49489..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/CommonsHttpClientTracer.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v2_0; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import java.net.URI; -import java.net.URISyntaxException; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.StatusLine; -import org.apache.commons.httpclient.URIException; - -public class CommonsHttpClientTracer extends HttpClientTracer { - private static final CommonsHttpClientTracer TRACER = new CommonsHttpClientTracer(); - - public static CommonsHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.apache-httpclient"; - } - - public Depth getCallDepth() { - return CallDepthThreadLocalMap.getCallDepth(HttpClient.class); - } - - @Override - protected String method(HttpMethod httpMethod) { - return httpMethod.getName(); - } - - @Override - protected URI url(HttpMethod httpMethod) throws URISyntaxException { - try { - // org.apache.commons.httpclient.URI -> java.net.URI - return new URI(httpMethod.getURI().toString()); - } catch (URIException e) { - throw new URISyntaxException("", e.getMessage()); - } - } - - @Override - protected Integer status(HttpMethod httpMethod) { - StatusLine statusLine = httpMethod.getStatusLine(); - return statusLine == null ? null : statusLine.getStatusCode(); - } - - @Override - protected String requestHeader(HttpMethod httpMethod, String name) { - Header header = httpMethod.getRequestHeader(name); - return header != null ? header.getValue() : null; - } - - @Override - protected String responseHeader(HttpMethod httpMethod, String name) { - Header header = httpMethod.getResponseHeader(name); - return header != null ? header.getValue() : null; - } - - @Override - protected Setter getSetter() { - return HttpHeadersInjectAdapter.SETTER; - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/HttpHeadersInjectAdapter.java b/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/HttpHeadersInjectAdapter.java deleted file mode 100644 index 807113a69c..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/HttpHeadersInjectAdapter.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v2_0; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpMethod; - -public class HttpHeadersInjectAdapter implements TextMapPropagator.Setter { - - public static final HttpHeadersInjectAdapter SETTER = new HttpHeadersInjectAdapter(); - - @Override - public void set(HttpMethod carrier, String key, String value) { - carrier.setRequestHeader(new Header(key, value)); - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/test/groovy/CommonsHttpClientTest.groovy b/instrumentation/apache-httpclient/apache-httpclient-2.0/src/test/groovy/CommonsHttpClientTest.groovy deleted file mode 100644 index ea8f8efa75..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-2.0/src/test/groovy/CommonsHttpClientTest.groovy +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import org.apache.commons.httpclient.HttpClient -import org.apache.commons.httpclient.HttpMethod -import org.apache.commons.httpclient.methods.DeleteMethod -import org.apache.commons.httpclient.methods.GetMethod -import org.apache.commons.httpclient.methods.HeadMethod -import org.apache.commons.httpclient.methods.OptionsMethod -import org.apache.commons.httpclient.methods.PostMethod -import org.apache.commons.httpclient.methods.PutMethod -import org.apache.commons.httpclient.methods.TraceMethod -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class CommonsHttpClientTest extends HttpClientTest { - @Shared - HttpClient client = new HttpClient() - - def setupSpec() { - client.setConnectionTimeout(CONNECT_TIMEOUT_MS) - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - HttpMethod httpMethod - - switch (method) { - case "GET": - httpMethod = new GetMethod(uri.toString()) - break - case "PUT": - httpMethod = new PutMethod(uri.toString()) - break - case "POST": - httpMethod = new PostMethod(uri.toString()) - break - case "HEAD": - httpMethod = new HeadMethod(uri.toString()) - break - case "DELETE": - httpMethod = new DeleteMethod(uri.toString()) - break - case "OPTIONS": - httpMethod = new OptionsMethod(uri.toString()) - break - case "TRACE": - httpMethod = new TraceMethod(uri.toString()) - break - default: - throw new RuntimeException("Unsupported method: " + method) - } - - headers.each { httpMethod.setRequestHeader(it.key, it.value) } - - try { - client.executeMethod(httpMethod) - callback?.call() - return httpMethod.getStatusCode() - } finally { - httpMethod.releaseConnection() - } - } - - @Override - boolean testRedirects() { - // Generates 4 spans - false - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/apache-httpclient-4.0.gradle b/instrumentation/apache-httpclient/apache-httpclient-4.0/apache-httpclient-4.0.gradle deleted file mode 100644 index fb8898ce24..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/apache-httpclient-4.0.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - fail { - group = "commons-httpclient" - module = "commons-httpclient" - versions = "[,4.0)" - skipVersions += '3.1-jenkins-1' - } - pass { - group = "org.apache.httpcomponents" - module = "httpclient" - versions = "[4.0,)" - assertInverse = true - } - pass { - // We want to support the dropwizard clients too. - group = 'io.dropwizard' - module = 'dropwizard-client' - versions = "(,)" - assertInverse = true - } -} - -dependencies { - library group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.0' -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientHelper.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientHelper.java deleted file mode 100644 index b9c7f2abdb..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpUriRequest; - -public class ApacheHttpClientHelper { - - public static SpanWithScope doMethodEnter(HttpUriRequest request) { - Span span = tracer().startSpan(request); - Scope scope = tracer().startScope(span, request); - return new SpanWithScope(span, scope); - } - - public static void doMethodExitAndResetCallDepthThread( - SpanWithScope spanWithScope, Object result, Throwable throwable) { - if (spanWithScope == null) { - return; - } - CallDepthThreadLocalMap.reset(HttpClient.class); - - doMethodExit(spanWithScope, result, throwable); - } - - public static void doMethodExit(SpanWithScope spanWithScope, Object result, Throwable throwable) { - try { - Span span = spanWithScope.getSpan(); - if (result instanceof HttpResponse) { - tracer().onResponse(span, (HttpResponse) result); - } // else they probably provided a ResponseHandler - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } finally { - spanWithScope.closeScope(); - } - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientInstrumentationModule.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientInstrumentationModule.java deleted file mode 100644 index 1a403a2853..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientInstrumentationModule.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpUriRequest; - -@AutoService(InstrumentationModule.class) -public class ApacheHttpClientInstrumentationModule extends InstrumentationModule { - - public ApacheHttpClientInstrumentationModule() { - super("apache-httpclient", "apache-httpclient-4.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HttpClientInstrumentation()); - } - - public static class HttpClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.apache.http.client.HttpClient"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.apache.http.client.HttpClient")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - // There are 8 execute(...) methods. Depending on the version, they may or may not delegate - // to eachother. Thus, all methods need to be instrumented. Because of argument position and - // type, some methods can share the same advice class. The call depth tracking ensures only 1 - // span is created - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(1)) - .and(takesArgument(0, named("org.apache.http.client.methods.HttpUriRequest"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$UriRequestAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(2)) - .and(takesArgument(0, named("org.apache.http.client.methods.HttpUriRequest"))) - .and(takesArgument(1, named("org.apache.http.protocol.HttpContext"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$UriRequestAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(2)) - .and(takesArgument(0, named("org.apache.http.client.methods.HttpUriRequest"))) - .and(takesArgument(1, named("org.apache.http.client.ResponseHandler"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$UriRequestWithHandlerAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(3)) - .and(takesArgument(0, named("org.apache.http.client.methods.HttpUriRequest"))) - .and(takesArgument(1, named("org.apache.http.client.ResponseHandler"))) - .and(takesArgument(2, named("org.apache.http.protocol.HttpContext"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$UriRequestWithHandlerAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(2)) - .and(takesArgument(0, named("org.apache.http.HttpHost"))) - .and(takesArgument(1, named("org.apache.http.HttpRequest"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$RequestAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(3)) - .and(takesArgument(0, named("org.apache.http.HttpHost"))) - .and(takesArgument(1, named("org.apache.http.HttpRequest"))) - .and(takesArgument(2, named("org.apache.http.protocol.HttpContext"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$RequestAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(3)) - .and(takesArgument(0, named("org.apache.http.HttpHost"))) - .and(takesArgument(1, named("org.apache.http.HttpRequest"))) - .and(takesArgument(2, named("org.apache.http.client.ResponseHandler"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$RequestWithHandlerAdvice"); - - transformers.put( - isMethod() - .and(named("execute")) - .and(not(isAbstract())) - .and(takesArguments(4)) - .and(takesArgument(0, named("org.apache.http.HttpHost"))) - .and(takesArgument(1, named("org.apache.http.HttpRequest"))) - .and(takesArgument(2, named("org.apache.http.client.ResponseHandler"))) - .and(takesArgument(3, named("org.apache.http.protocol.HttpContext"))), - ApacheHttpClientInstrumentationModule.class.getName() + "$RequestWithHandlerAdvice"); - - return transformers; - } - } - - public static class UriRequestAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope methodEnter(@Advice.Argument(0) HttpUriRequest request) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(HttpClient.class); - if (callDepth > 0) { - return null; - } - - return ApacheHttpClientHelper.doMethodEnter(request); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Return Object result, - @Advice.Thrown Throwable throwable) { - ApacheHttpClientHelper.doMethodExitAndResetCallDepthThread(spanWithScope, result, throwable); - } - } - - public static class UriRequestWithHandlerAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope methodEnter( - @Advice.Argument(0) HttpUriRequest request, - @Advice.Argument( - value = 1, - optional = true, - typing = Assigner.Typing.DYNAMIC, - readOnly = false) - Object handler) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(HttpClient.class); - if (callDepth > 0) { - return null; - } - - SpanWithScope spanWithScope = ApacheHttpClientHelper.doMethodEnter(request); - - // Wrap the handler so we capture the status code - if (handler instanceof ResponseHandler) { - handler = - new WrappingStatusSettingResponseHandler( - spanWithScope.getSpan(), (ResponseHandler) handler); - } - return spanWithScope; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Return Object result, - @Advice.Thrown Throwable throwable) { - ApacheHttpClientHelper.doMethodExitAndResetCallDepthThread(spanWithScope, result, throwable); - } - } - - public static class RequestAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope methodEnter( - @Advice.Argument(0) HttpHost host, @Advice.Argument(1) HttpRequest request) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(HttpClient.class); - if (callDepth > 0) { - return null; - } - - if (request instanceof HttpUriRequest) { - return ApacheHttpClientHelper.doMethodEnter((HttpUriRequest) request); - } else { - return ApacheHttpClientHelper.doMethodEnter( - new HostAndRequestAsHttpUriRequest(host, request)); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Return Object result, - @Advice.Thrown Throwable throwable) { - ApacheHttpClientHelper.doMethodExitAndResetCallDepthThread(spanWithScope, result, throwable); - } - } - - public static class RequestWithHandlerAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope methodEnter( - @Advice.Argument(0) HttpHost host, - @Advice.Argument(1) HttpRequest request, - @Advice.Argument( - value = 2, - optional = true, - typing = Assigner.Typing.DYNAMIC, - readOnly = false) - Object handler) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(HttpClient.class); - if (callDepth > 0) { - return null; - } - - SpanWithScope spanWithScope; - - if (request instanceof HttpUriRequest) { - spanWithScope = ApacheHttpClientHelper.doMethodEnter((HttpUriRequest) request); - } else { - spanWithScope = - ApacheHttpClientHelper.doMethodEnter(new HostAndRequestAsHttpUriRequest(host, request)); - } - - // Wrap the handler so we capture the status code - if (handler instanceof ResponseHandler) { - handler = - new WrappingStatusSettingResponseHandler( - spanWithScope.getSpan(), (ResponseHandler) handler); - } - return spanWithScope; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Return Object result, - @Advice.Thrown Throwable throwable) { - ApacheHttpClientHelper.doMethodExitAndResetCallDepthThread(spanWithScope, result, throwable); - } - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientTracer.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientTracer.java deleted file mode 100644 index f46fb4c725..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientTracer.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.HttpHeadersInjectAdapter.SETTER; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import org.apache.http.Header; -import org.apache.http.HttpMessage; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpUriRequest; -import org.checkerframework.checker.nullness.qual.Nullable; - -class ApacheHttpClientTracer - extends HttpClientTracer { - - private static final ApacheHttpClientTracer TRACER = new ApacheHttpClientTracer(); - - public static ApacheHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpUriRequest httpRequest) { - return httpRequest.getMethod(); - } - - @Override - protected @Nullable String flavor(HttpUriRequest httpUriRequest) { - return httpUriRequest.getProtocolVersion().toString(); - } - - @Override - protected URI url(HttpUriRequest request) { - return request.getURI(); - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.getStatusLine().getStatusCode(); - } - - @Override - protected String requestHeader(HttpUriRequest request, String name) { - return header(request, name); - } - - @Override - protected String responseHeader(HttpResponse response, String name) { - return header(response, name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - private static String header(HttpMessage message, String name) { - Header header = message.getFirstHeader(name); - return header != null ? header.getValue() : null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.apache-httpclient"; - } - - /** This method is overridden to allow other classes in this package to call it. */ - @Override - protected Span onResponse(Span span, HttpResponse httpResponse) { - return super.onResponse(span, httpResponse); - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/HostAndRequestAsHttpUriRequest.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/HostAndRequestAsHttpUriRequest.java deleted file mode 100644 index 18e274ed5e..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/HostAndRequestAsHttpUriRequest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; - -import java.net.URI; -import java.net.URISyntaxException; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.ProtocolVersion; -import org.apache.http.RequestLine; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.message.AbstractHttpMessage; - -/** Wraps HttpHost and HttpRequest into a HttpUriRequest for tracers and injectors. */ -public class HostAndRequestAsHttpUriRequest extends AbstractHttpMessage implements HttpUriRequest { - - private final String method; - private final RequestLine requestLine; - private final ProtocolVersion protocolVersion; - private final java.net.URI uri; - - private final HttpRequest actualRequest; - - public HostAndRequestAsHttpUriRequest(HttpHost httpHost, HttpRequest httpRequest) { - - method = httpRequest.getRequestLine().getMethod(); - requestLine = httpRequest.getRequestLine(); - protocolVersion = requestLine.getProtocolVersion(); - - URI calculatedUri; - try { - calculatedUri = new URI(httpHost.toURI() + httpRequest.getRequestLine().getUri()); - } catch (URISyntaxException e) { - calculatedUri = null; - } - uri = calculatedUri; - actualRequest = httpRequest; - } - - @Override - public void abort() throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isAborted() { - return false; - } - - @Override - public void addHeader(String name, String value) { - actualRequest.addHeader(name, value); - } - - @Override - public String getMethod() { - return method; - } - - @Override - public RequestLine getRequestLine() { - return requestLine; - } - - @Override - public ProtocolVersion getProtocolVersion() { - return protocolVersion; - } - - @Override - public java.net.URI getURI() { - return uri; - } - - public HttpRequest getActualRequest() { - return actualRequest; - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/HttpHeadersInjectAdapter.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/HttpHeadersInjectAdapter.java deleted file mode 100644 index 4afd43d798..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/HttpHeadersInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.apache.http.client.methods.HttpUriRequest; - -class HttpHeadersInjectAdapter implements TextMapPropagator.Setter { - - public static final HttpHeadersInjectAdapter SETTER = new HttpHeadersInjectAdapter(); - - @Override - public void set(HttpUriRequest carrier, String key, String value) { - carrier.addHeader(key, value); - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/WrappingStatusSettingResponseHandler.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/WrappingStatusSettingResponseHandler.java deleted file mode 100644 index 0904e0ddea..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/WrappingStatusSettingResponseHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import java.io.IOException; -import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.ResponseHandler; - -public class WrappingStatusSettingResponseHandler implements ResponseHandler { - final Span span; - final ResponseHandler handler; - - public WrappingStatusSettingResponseHandler(Span span, ResponseHandler handler) { - this.span = span; - this.handler = handler; - } - - @Override - public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException { - if (null != span) { - tracer().onResponse(span, response); - } - return handler.handleResponse(response); - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy deleted file mode 100644 index cd004c7dc0..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import org.apache.http.HttpResponse -import org.apache.http.client.ResponseHandler -import org.apache.http.impl.client.DefaultHttpClient -import org.apache.http.message.BasicHeader -import org.apache.http.params.HttpConnectionParams -import org.apache.http.params.HttpParams -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class ApacheHttpClientResponseHandlerTest extends HttpClientTest { - - @Shared - def client = new DefaultHttpClient() - - @Shared - def handler = new ResponseHandler() { - @Override - Integer handleResponse(HttpResponse response) { - return response.statusLine.statusCode - } - } - - def setupSpec() { - HttpParams httpParams = client.getParams() - HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT_MS) - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = new HttpUriRequest(method, uri) - headers.entrySet().each { - request.addHeader(new BasicHeader(it.key, it.value)) - } - - def status = client.execute(request, handler) - - // handler execution is included within the client span, so we can't call the callback there. - callback?.call() - - return status - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/ApacheHttpClientTest.groovy b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/ApacheHttpClientTest.groovy deleted file mode 100644 index 233b2abe64..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/ApacheHttpClientTest.groovy +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import org.apache.http.HttpHost -import org.apache.http.HttpRequest -import org.apache.http.HttpResponse -import org.apache.http.impl.client.DefaultHttpClient -import org.apache.http.message.BasicHeader -import org.apache.http.message.BasicHttpRequest -import org.apache.http.params.HttpConnectionParams -import org.apache.http.params.HttpParams -import org.apache.http.protocol.BasicHttpContext -import spock.lang.Shared -import spock.lang.Timeout - -abstract class ApacheHttpClientTest extends HttpClientTest { - @Shared - def client = new DefaultHttpClient() - - def setupSpec() { - HttpParams httpParams = client.getParams() - HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT_MS) - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = createRequest(method, uri) - headers.entrySet().each { - request.addHeader(new BasicHeader(it.key, it.value)) - } - - def response = executeRequest(request, uri) - callback?.call() - response.entity?.content?.close() // Make sure the connection is closed. - - return response.statusLine.statusCode - } - - abstract T createRequest(String method, URI uri) - - abstract HttpResponse executeRequest(T request, URI uri) - - static String fullPathFromURI(URI uri) { - StringBuilder builder = new StringBuilder() - if (uri.getPath() != null) { - builder.append(uri.getPath()) - } - - if (uri.getQuery() != null) { - builder.append('?') - builder.append(uri.getQuery()) - } - - if (uri.getFragment() != null) { - builder.append('#') - builder.append(uri.getFragment()) - } - return builder.toString() - } -} - -@Timeout(5) -class ApacheClientHostRequest extends ApacheHttpClientTest { - @Override - BasicHttpRequest createRequest(String method, URI uri) { - return new BasicHttpRequest(method, fullPathFromURI(uri)) - } - - @Override - HttpResponse executeRequest(BasicHttpRequest request, URI uri) { - return client.execute(new HttpHost(uri.getHost(), uri.getPort()), request) - } - - @Override - boolean testRemoteConnection() { - return false - } -} - -@Timeout(5) -class ApacheClientHostRequestContext extends ApacheHttpClientTest { - @Override - BasicHttpRequest createRequest(String method, URI uri) { - return new BasicHttpRequest(method, fullPathFromURI(uri)) - } - - @Override - HttpResponse executeRequest(BasicHttpRequest request, URI uri) { - return client.execute(new HttpHost(uri.getHost(), uri.getPort()), request, new BasicHttpContext()) - } - - @Override - boolean testRemoteConnection() { - return false - } -} - -@Timeout(5) -class ApacheClientHostRequestResponseHandler extends ApacheHttpClientTest { - @Override - BasicHttpRequest createRequest(String method, URI uri) { - return new BasicHttpRequest(method, fullPathFromURI(uri)) - } - - @Override - HttpResponse executeRequest(BasicHttpRequest request, URI uri) { - return client.execute(new HttpHost(uri.getHost(), uri.getPort()), request, { response -> response }) - } - - @Override - boolean testRemoteConnection() { - return false - } -} - -@Timeout(5) -class ApacheClientHostRequestResponseHandlerContext extends ApacheHttpClientTest { - @Override - BasicHttpRequest createRequest(String method, URI uri) { - return new BasicHttpRequest(method, fullPathFromURI(uri)) - } - - @Override - HttpResponse executeRequest(BasicHttpRequest request, URI uri) { - return client.execute(new HttpHost(uri.getHost(), uri.getPort()), request, { response -> response }, new BasicHttpContext()) - } - - @Override - boolean testRemoteConnection() { - return false - } -} - -@Timeout(5) -class ApacheClientUriRequest extends ApacheHttpClientTest { - @Override - HttpUriRequest createRequest(String method, URI uri) { - return new HttpUriRequest(method, uri) - } - - @Override - HttpResponse executeRequest(HttpUriRequest request, URI uri) { - return client.execute(request) - } -} - -@Timeout(5) -class ApacheClientUriRequestContext extends ApacheHttpClientTest { - @Override - HttpUriRequest createRequest(String method, URI uri) { - return new HttpUriRequest(method, uri) - } - - @Override - HttpResponse executeRequest(HttpUriRequest request, URI uri) { - return client.execute(request, new BasicHttpContext()) - } -} - -@Timeout(5) -class ApacheClientUriRequestResponseHandler extends ApacheHttpClientTest { - @Override - HttpUriRequest createRequest(String method, URI uri) { - return new HttpUriRequest(method, uri) - } - - @Override - HttpResponse executeRequest(HttpUriRequest request, URI uri) { - return client.execute(request, { response -> response }) - } -} - -@Timeout(5) -class ApacheClientUriRequestResponseHandlerContext extends ApacheHttpClientTest { - @Override - HttpUriRequest createRequest(String method, URI uri) { - return new HttpUriRequest(method, uri) - } - - @Override - HttpResponse executeRequest(HttpUriRequest request, URI uri) { - return client.execute(request, { response -> response }) - } -} diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/HttpUriRequest.groovy b/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/HttpUriRequest.groovy deleted file mode 100644 index 4a3c7bd57b..0000000000 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/src/test/groovy/HttpUriRequest.groovy +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.apache.http.client.methods.HttpRequestBase - -class HttpUriRequest extends HttpRequestBase { - - private final String methodName - - HttpUriRequest(final String methodName, final URI uri) { - this.methodName = methodName - setURI(uri) - } - - @Override - String getMethod() { - return methodName - } -} diff --git a/instrumentation/async-http-client-1.9/async-http-client-1.9.gradle b/instrumentation/async-http-client-1.9/async-http-client-1.9.gradle deleted file mode 100644 index 23c6e49a2c..0000000000 --- a/instrumentation/async-http-client-1.9/async-http-client-1.9.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.ning" - module = "async-http-client" - versions = "[1.9.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'com.ning', name: 'async-http-client', version: '1.9.0' -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInjectAdapter.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInjectAdapter.java deleted file mode 100644 index 45c532463c..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import com.ning.http.client.Request; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class AsyncHttpClientInjectAdapter implements TextMapPropagator.Setter { - - public static final AsyncHttpClientInjectAdapter SETTER = new AsyncHttpClientInjectAdapter(); - - @Override - public void set(Request carrier, String key, String value) { - carrier.getHeaders().replaceWith(key, value); - } -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java deleted file mode 100644 index cee20d454f..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.Pair; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; - -@AutoService(io.opentelemetry.javaagent.tooling.InstrumentationModule.class) -public class AsyncHttpClientInstrumentationModule - extends io.opentelemetry.javaagent.tooling.InstrumentationModule { - public AsyncHttpClientInstrumentationModule() { - super("async-http-client", "async-http-client-1.9"); - } - - @Override - public List typeInstrumentations() { - return asList(new RequestInstrumentation(), new ResponseInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName()); - } -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientTracer.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientTracer.java deleted file mode 100644 index 48355b6e89..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientTracer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import com.ning.http.client.Request; -import com.ning.http.client.Response; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; - -public class AsyncHttpClientTracer extends HttpClientTracer { - - private static final AsyncHttpClientTracer TRACER = new AsyncHttpClientTracer(); - - public static AsyncHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(Request request) { - return request.getMethod(); - } - - @Override - protected URI url(Request request) throws URISyntaxException { - return request.getUri().toJavaNetURI(); - } - - @Override - protected Integer status(Response response) { - return response.getStatusCode(); - } - - @Override - protected String requestHeader(Request request, String name) { - return request.getHeaders().getFirstValue(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.getHeaders().getFirstValue(name); - } - - @Override - protected Setter getSetter() { - return AsyncHttpClientInjectAdapter.SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.async-http-client"; - } -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/RequestAdvice.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/RequestAdvice.java deleted file mode 100644 index 6d1ae8c5c3..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/RequestAdvice.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import com.ning.http.client.AsyncHandler; -import com.ning.http.client.Request; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.Pair; -import net.bytebuddy.asm.Advice; - -public class RequestAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope onEnter( - @Advice.Argument(0) Request request, @Advice.Argument(1) AsyncHandler handler) { - Context parentContext = Java8BytecodeBridge.currentContext(); - - Span span = AsyncHttpClientTracer.tracer().startSpan(request); - InstrumentationContext.get(AsyncHandler.class, Pair.class) - .put(handler, Pair.of(parentContext, span)); - return AsyncHttpClientTracer.tracer().startScope(span, request); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit(@Advice.Enter Scope scope) { - // span closed in ClientResponseAdvice - scope.close(); - } -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/RequestInstrumentation.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/RequestInstrumentation.java deleted file mode 100644 index 83ffba5d0e..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/RequestInstrumentation.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class RequestInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.ning.http.client.AsyncHttpClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("executeRequest") - .and(takesArgument(0, named("com.ning.http.client.Request"))) - .and(takesArgument(1, named("com.ning.http.client.AsyncHandler"))) - .and(isPublic()), - RequestAdvice.class.getName()); - } -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/ResponseAdvice.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/ResponseAdvice.java deleted file mode 100644 index 513ffc18de..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/ResponseAdvice.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import com.ning.http.client.AsyncCompletionHandler; -import com.ning.http.client.AsyncHandler; -import com.ning.http.client.Response; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Pair; -import net.bytebuddy.asm.Advice; - -public class ResponseAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope onEnter( - @Advice.This AsyncCompletionHandler handler, @Advice.Argument(0) Response response) { - - // TODO I think all this should happen on exit, not on enter. - // After response was handled by user provided handler. - ContextStore contextStore = - InstrumentationContext.get(AsyncHandler.class, Pair.class); - Pair spanWithParent = contextStore.get(handler); - if (null != spanWithParent) { - contextStore.put(handler, null); - } - if (spanWithParent.hasRight()) { - AsyncHttpClientTracer.tracer().end(spanWithParent.getRight(), response); - } - return spanWithParent.hasLeft() ? spanWithParent.getLeft().makeCurrent() : null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit(@Advice.Enter Scope scope) { - if (null != scope) { - scope.close(); - } - } -} diff --git a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/ResponseInstrumentation.java b/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/ResponseInstrumentation.java deleted file mode 100644 index dfacffd7d3..0000000000 --- a/instrumentation/async-http-client-1.9/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/ResponseInstrumentation.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.asynchttpclient; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.hasSuperClass; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class ResponseInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.ning.http.client.AsyncCompletionHandler"); - } - - @Override - public ElementMatcher typeMatcher() { - return hasSuperClass(named("com.ning.http.client.AsyncCompletionHandler")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("onCompleted") - .and(takesArgument(0, named("com.ning.http.client.Response"))) - .and(isPublic()), - ResponseAdvice.class.getName()); - } -} diff --git a/instrumentation/async-http-client-1.9/src/test/groovy/AsyncHttpClientTest.groovy b/instrumentation/async-http-client-1.9/src/test/groovy/AsyncHttpClientTest.groovy deleted file mode 100644 index 6fedc3e551..0000000000 --- a/instrumentation/async-http-client-1.9/src/test/groovy/AsyncHttpClientTest.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.ning.http.client.AsyncCompletionHandler -import com.ning.http.client.AsyncHttpClient -import com.ning.http.client.Request -import com.ning.http.client.RequestBuilder -import com.ning.http.client.Response -import com.ning.http.client.uri.Uri -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.AutoCleanup -import spock.lang.Shared - -class AsyncHttpClientTest extends HttpClientTest { - - @AutoCleanup - @Shared - def client = new AsyncHttpClient() - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - - RequestBuilder requestBuilder = new RequestBuilder(method) - .setUri(Uri.create(uri.toString())) - headers.entrySet().each { - requestBuilder.addHeader(it.key, it.value) - } - Request request = requestBuilder.build() - - def handler = new AsyncCompletionHandler() { - @Override - Object onCompleted(Response response) throws Exception { - if (callback != null) { - callback() - } - return response - } - } - - def response = client.executeRequest(request, handler).get() - response.statusCode - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } -} - - diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/aws-sdk-1.11.gradle b/instrumentation/aws-sdk/aws-sdk-1.11/aws-sdk-1.11.gradle deleted file mode 100644 index 23fd3c88f0..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/aws-sdk-1.11.gradle +++ /dev/null @@ -1,72 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply plugin: 'org.unbroken-dome.test-sets' - -// compiling against 1.11.0, but instrumentation should work against 1.10.33 with varying effects, -// depending on the version's implementation. (i.e. DeleteOptionGroup may have less handlerCounts than -// expected in 1.11.84. Testing against 1.11.0 instead of 1.10.33 because the RequestHandler class -// used in testing is abstract in 1.10.33 -// keeping base test version on 1.11.0 because RequestHandler2 is abstract in 1.10.33, -// therefore keeping base version as 1.11.0 even though the instrumentation probably -// is able to support up to 1.10.33 -muzzle { - pass { - group = "com.amazonaws" - module = "aws-java-sdk-core" - versions = "[1.10.33,)" - assertInverse = true - } -} - -testSets { - // Features used in test_1_11_106 (builder) is available since 1.11.84, but - // using 1.11.106 because of previous concerns with byte code differences - // in 1.11.106, also, the DeleteOptionGroup request generates more spans - // in 1.11.106 than 1.11.84. - // We test older version in separate test set to test newer version and latest deps in the 'default' - // test dir. Otherwise we get strange warnings in Idea. - test_before_1_11_106 { - filter { - // this is needed because "test.dependsOn test_before_1_11_106", and so without this, - // running a single test in the default test set will fail - setFailOnNoMatchingTests(false) - } - } -} - -configurations { - test_before_1_11_106RuntimeClasspath { - resolutionStrategy.force 'com.amazonaws:aws-java-sdk-s3:1.11.0' - resolutionStrategy.force 'com.amazonaws:aws-java-sdk-rds:1.11.0' - resolutionStrategy.force 'com.amazonaws:aws-java-sdk-ec2:1.11.0' - resolutionStrategy.force 'com.amazonaws:aws-java-sdk-kinesis:1.11.0' - resolutionStrategy.force 'com.amazonaws:aws-java-sdk-sqs:1.11.0' - resolutionStrategy.force 'com.amazonaws:aws-java-sdk-dynamodb:1.11.0' - } -} - -dependencies { - library group: 'com.amazonaws', name: 'aws-java-sdk-core', version: '1.11.0' - - // Include httpclient instrumentation for testing because it is a dependency for aws-sdk. - testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-4.0') - testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.106' - testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-rds', version: '1.11.106' - testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.106' - testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-kinesis', version: '1.11.106' - testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-sqs', version: '1.11.106' - testLibrary group: 'com.amazonaws', name: 'aws-java-sdk-dynamodb', version: '1.11.106' - - // needed for kinesis: - testImplementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-cbor', version: versions.jackson - - test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.0') - test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-rds', version: '1.11.0') - test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.0') - test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-kinesis', version: '1.11.0') - test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-sqs', version: '1.11.0') - test_before_1_11_106Implementation(group: 'com.amazonaws', name: 'aws-java-sdk-dynamodb', version: '1.11.0') -} - -if (!testLatestDeps) { - test.dependsOn test_before_1_11_106 -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsClientInstrumentation.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsClientInstrumentation.java deleted file mode 100644 index 63acedf97e..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsClientInstrumentation.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresField; -import static net.bytebuddy.matcher.ElementMatchers.isConstructor; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.amazonaws.AmazonWebServiceRequest; -import com.amazonaws.handlers.RequestHandler2; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * This instrumentation might work with versions before 1.11.0, but this was the first version that - * is tested. It could possibly be extended earlier. - */ -public class AwsClientInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.amazonaws.AmazonWebServiceClient") - .and(declaresField(named("requestHandler2s"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isConstructor(), AwsClientInstrumentation.class.getName() + "$AwsClientAdvice"); - } - - public static class AwsClientAdvice { - // Since we're instrumenting the constructor, we can't add onThrowable. - @Advice.OnMethodExit(suppress = Throwable.class) - public static void addHandler( - @Advice.FieldValue("requestHandler2s") List handlers) { - boolean hasAgentHandler = false; - for (RequestHandler2 handler : handlers) { - if (handler instanceof TracingRequestHandler) { - hasAgentHandler = true; - break; - } - } - if (!hasAgentHandler) { - handlers.add( - new TracingRequestHandler( - InstrumentationContext.get(AmazonWebServiceRequest.class, RequestMeta.class))); - } - } - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsHttpClientInstrumentation.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsHttpClientInstrumentation.java deleted file mode 100644 index 47079d5329..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsHttpClientInstrumentation.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import static io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.AwsSdkClientTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.RequestMeta.SPAN_SCOPE_PAIR_CONTEXT_KEY; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.amazonaws.AmazonClientException; -import com.amazonaws.Request; -import com.amazonaws.handlers.RequestHandler2; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * This is additional 'helper' to catch cases when HTTP request throws exception different from - * {@link AmazonClientException} (for example an error thrown by another handler). In these cases - * {@link RequestHandler2#afterError} is not called. - */ -public class AwsHttpClientInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.amazonaws.http.AmazonHttpClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(not(isAbstract())).and(named("doExecute")), - AwsHttpClientInstrumentation.class.getName() + "$HttpClientAdvice"); - } - - public static class HttpClientAdvice { - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Argument(value = 0, optional = true) Request request, - @Advice.Thrown Throwable throwable) { - if (throwable != null) { - SpanWithScope scope = request.getHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY); - if (scope != null) { - request.addHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY, null); - tracer().endExceptionally(scope.getSpan(), throwable); - scope.closeScope(); - } - } - } - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkClientTracer.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkClientTracer.java deleted file mode 100644 index 6b373841ef..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkClientTracer.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import com.amazonaws.AmazonWebServiceRequest; -import com.amazonaws.AmazonWebServiceResponse; -import com.amazonaws.Request; -import com.amazonaws.Response; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.util.concurrent.ConcurrentHashMap; - -public class AwsSdkClientTracer extends HttpClientTracer, Request, Response> { - - static final String COMPONENT_NAME = "java-aws-sdk"; - - private static final AwsSdkClientTracer TRACER = new AwsSdkClientTracer(); - - public static AwsSdkClientTracer tracer() { - return TRACER; - } - - private final NamesCache namesCache = new NamesCache(); - - public AwsSdkClientTracer() {} - - @Override - public String spanNameForRequest(Request request) { - if (request == null) { - return DEFAULT_SPAN_NAME; - } - String awsServiceName = request.getServiceName(); - Class awsOperation = request.getOriginalRequest().getClass(); - return qualifiedOperation(awsServiceName, awsOperation); - } - - public Span startSpan(Request request, RequestMeta requestMeta) { - Span span = super.startSpan(request); - - String awsServiceName = request.getServiceName(); - AmazonWebServiceRequest originalRequest = request.getOriginalRequest(); - Class awsOperation = originalRequest.getClass(); - - span.setAttribute("aws.agent", COMPONENT_NAME); - span.setAttribute("aws.service", awsServiceName); - span.setAttribute("aws.operation", awsOperation.getSimpleName()); - span.setAttribute("aws.endpoint", request.getEndpoint().toString()); - - if (requestMeta != null) { - span.setAttribute("aws.bucket.name", requestMeta.getBucketName()); - span.setAttribute("aws.queue.url", requestMeta.getQueueUrl()); - span.setAttribute("aws.queue.name", requestMeta.getQueueName()); - span.setAttribute("aws.stream.name", requestMeta.getStreamName()); - span.setAttribute("aws.table.name", requestMeta.getTableName()); - } - return span; - } - - @Override - public Span onResponse(Span span, Response response) { - if (response != null && response.getAwsResponse() instanceof AmazonWebServiceResponse) { - AmazonWebServiceResponse awsResp = (AmazonWebServiceResponse) response.getAwsResponse(); - span.setAttribute("aws.requestId", awsResp.getRequestId()); - } - return super.onResponse(span, response); - } - - private String qualifiedOperation(String service, Class operation) { - ConcurrentHashMap cache = namesCache.get(operation); - String qualified = cache.get(service); - if (qualified == null) { - qualified = - service.replace("Amazon", "").trim() - + '.' - + operation.getSimpleName().replace("Request", ""); - cache.put(service, qualified); - } - return qualified; - } - - @Override - protected String method(Request request) { - return request.getHttpMethod().name(); - } - - @Override - protected URI url(Request request) { - return request.getEndpoint(); - } - - @Override - protected Integer status(Response response) { - return response.getHttpResponse().getStatusCode(); - } - - @Override - protected String requestHeader(Request request, String name) { - return request.getHeaders().get(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.getHttpResponse().getHeaders().get(name); - } - - @Override - protected Setter> getSetter() { - return AwsSdkInjectAdapter.INSTANCE; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.aws-sdk"; - } - - static final class NamesCache extends ClassValue> { - @Override - protected ConcurrentHashMap computeValue(Class type) { - return new ConcurrentHashMap<>(); - } - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInjectAdapter.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInjectAdapter.java deleted file mode 100644 index 49263b80af..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import com.amazonaws.Request; -import io.opentelemetry.context.propagation.TextMapPropagator; - -final class AwsSdkInjectAdapter implements TextMapPropagator.Setter> { - - static final AwsSdkInjectAdapter INSTANCE = new AwsSdkInjectAdapter(); - - @Override - public void set(Request request, String name, String value) { - request.addHeader(name, value); - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java deleted file mode 100644 index 0a0dbac6a5..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class AwsSdkInstrumentationModule extends InstrumentationModule { - public AwsSdkInstrumentationModule() { - super("aws-sdk", "aws-sdk-1.11"); - } - - @Override - public List typeInstrumentations() { - return asList( - new AwsClientInstrumentation(), - new AwsHttpClientInstrumentation(), - new RequestExecutorInstrumentation(), - new RequestInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap( - "com.amazonaws.AmazonWebServiceRequest", - "io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.RequestMeta"); - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestExecutorInstrumentation.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestExecutorInstrumentation.java deleted file mode 100644 index 6934483b10..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestExecutorInstrumentation.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import static io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.AwsSdkClientTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.RequestMeta.SPAN_SCOPE_PAIR_CONTEXT_KEY; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.amazonaws.Request; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * Due to a change in the AmazonHttpClient class, this instrumentation is needed to support newer - * versions. The {@link AwsHttpClientInstrumentation} class should cover older versions. - */ -public class RequestExecutorInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.amazonaws.http.AmazonHttpClient$RequestExecutor"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(not(isAbstract())).and(named("doExecute")), - RequestExecutorInstrumentation.class.getName() + "$RequestExecutorAdvice"); - } - - public static class RequestExecutorAdvice { - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.FieldValue("request") Request request, @Advice.Thrown Throwable throwable) { - if (throwable != null) { - SpanWithScope scope = request.getHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY); - if (scope != null) { - request.addHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY, null); - tracer().endExceptionally(scope.getSpan(), throwable); - scope.closeScope(); - } - } - } - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestInstrumentation.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestInstrumentation.java deleted file mode 100644 index dfe16ef2e3..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestInstrumentation.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.amazonaws.AmazonWebServiceRequest; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class RequestInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.amazonaws.AmazonWebServiceRequest"); - } - - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("com.amazonaws.services.") - .and(extendsClass(named("com.amazonaws.AmazonWebServiceRequest"))); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("setBucketName").and(takesArgument(0, String.class)), - RequestInstrumentation.class.getName() + "$BucketNameAdvice"); - transformers.put( - named("setQueueUrl").and(takesArgument(0, String.class)), - RequestInstrumentation.class.getName() + "$QueueUrlAdvice"); - transformers.put( - named("setQueueName").and(takesArgument(0, String.class)), - RequestInstrumentation.class.getName() + "$QueueNameAdvice"); - transformers.put( - named("setStreamName").and(takesArgument(0, String.class)), - RequestInstrumentation.class.getName() + "$StreamNameAdvice"); - transformers.put( - named("setTableName").and(takesArgument(0, String.class)), - RequestInstrumentation.class.getName() + "$TableNameAdvice"); - return transformers; - } - - public static class BucketNameAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) String value, @Advice.This AmazonWebServiceRequest request) { - ContextStore contextStore = - InstrumentationContext.get(AmazonWebServiceRequest.class, RequestMeta.class); - RequestMeta requestMeta = contextStore.get(request); - if (requestMeta == null) { - requestMeta = new RequestMeta(); - contextStore.put(request, requestMeta); - } - requestMeta.setBucketName(value); - } - } - - public static class QueueUrlAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) String value, @Advice.This AmazonWebServiceRequest request) { - ContextStore contextStore = - InstrumentationContext.get(AmazonWebServiceRequest.class, RequestMeta.class); - RequestMeta requestMeta = contextStore.get(request); - if (requestMeta == null) { - requestMeta = new RequestMeta(); - contextStore.put(request, requestMeta); - } - requestMeta.setQueueUrl(value); - } - } - - public static class QueueNameAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) String value, @Advice.This AmazonWebServiceRequest request) { - ContextStore contextStore = - InstrumentationContext.get(AmazonWebServiceRequest.class, RequestMeta.class); - RequestMeta requestMeta = contextStore.get(request); - if (requestMeta == null) { - requestMeta = new RequestMeta(); - contextStore.put(request, requestMeta); - } - requestMeta.setQueueName(value); - } - } - - public static class StreamNameAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) String value, @Advice.This AmazonWebServiceRequest request) { - ContextStore contextStore = - InstrumentationContext.get(AmazonWebServiceRequest.class, RequestMeta.class); - RequestMeta requestMeta = contextStore.get(request); - if (requestMeta == null) { - requestMeta = new RequestMeta(); - contextStore.put(request, requestMeta); - } - requestMeta.setStreamName(value); - } - } - - public static class TableNameAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) String value, @Advice.This AmazonWebServiceRequest request) { - ContextStore contextStore = - InstrumentationContext.get(AmazonWebServiceRequest.class, RequestMeta.class); - RequestMeta requestMeta = contextStore.get(request); - if (requestMeta == null) { - requestMeta = new RequestMeta(); - contextStore.put(request, requestMeta); - } - requestMeta.setTableName(value); - } - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestMeta.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestMeta.java deleted file mode 100644 index 24edd079a8..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RequestMeta.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import com.amazonaws.handlers.HandlerContextKey; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import java.util.Objects; - -public class RequestMeta { - // Note: aws1.x sdk doesn't have any truly async clients so we can store scope in request context - // safely. - public static final HandlerContextKey SPAN_SCOPE_PAIR_CONTEXT_KEY = - new HandlerContextKey<>("io.opentelemetry.auto.SpanWithScope"); - - private String bucketName; - private String queueUrl; - private String queueName; - private String streamName; - private String tableName; - - public String getBucketName() { - return bucketName; - } - - public void setBucketName(String bucketName) { - this.bucketName = bucketName; - } - - public String getQueueUrl() { - return queueUrl; - } - - public void setQueueUrl(String queueUrl) { - this.queueUrl = queueUrl; - } - - public String getQueueName() { - return queueName; - } - - public void setQueueName(String queueName) { - this.queueName = queueName; - } - - public String getStreamName() { - return streamName; - } - - public void setStreamName(String streamName) { - this.streamName = streamName; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof RequestMeta)) { - return false; - } - RequestMeta other = (RequestMeta) obj; - return Objects.equals(bucketName, other.bucketName) - && Objects.equals(queueUrl, other.queueUrl) - && Objects.equals(queueName, other.queueName) - && Objects.equals(streamName, other.streamName) - && Objects.equals(tableName, other.tableName); - } - - @Override - public int hashCode() { - return Objects.hash(bucketName, queueUrl, queueName, streamName, tableName); - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java deleted file mode 100644 index cb68f8d413..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; - -import static io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.AwsSdkClientTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.awssdk.v1_11.RequestMeta.SPAN_SCOPE_PAIR_CONTEXT_KEY; - -import com.amazonaws.AmazonWebServiceRequest; -import com.amazonaws.Request; -import com.amazonaws.Response; -import com.amazonaws.handlers.RequestHandler2; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; - -/** Tracing Request Handler. */ -public class TracingRequestHandler extends RequestHandler2 { - - private final ContextStore contextStore; - - public TracingRequestHandler(ContextStore contextStore) { - this.contextStore = contextStore; - } - - @Override - public void beforeRequest(Request request) { - AmazonWebServiceRequest originalRequest = request.getOriginalRequest(); - RequestMeta requestMeta = contextStore.get(originalRequest); - Span span = tracer().startSpan(request, requestMeta); - Scope scope = tracer().startScope(span, request); - request.addHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY, new SpanWithScope(span, scope)); - } - - @Override - public void afterResponse(Request request, Response response) { - SpanWithScope scope = request.getHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY); - if (scope != null) { - request.addHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY, null); - scope.closeScope(); - tracer().end(scope.getSpan(), response); - } - } - - @Override - public void afterError(Request request, Response response, Exception e) { - SpanWithScope scope = request.getHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY); - if (scope != null) { - request.addHandlerContext(SPAN_SCOPE_PAIR_CONTEXT_KEY, null); - scope.closeScope(); - tracer().endExceptionally(scope.getSpan(), response, e); - } - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/test/groovy/Aws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/src/test/groovy/Aws1ClientTest.groovy deleted file mode 100644 index e7bf08f65c..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/test/groovy/Aws1ClientTest.groovy +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.server.http.TestHttpServer.httpServer -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT - -import com.amazonaws.AmazonClientException -import com.amazonaws.AmazonWebServiceClient -import com.amazonaws.ClientConfiguration -import com.amazonaws.Request -import com.amazonaws.SDKGlobalConfiguration -import com.amazonaws.SdkClientException -import com.amazonaws.auth.AWSCredentialsProviderChain -import com.amazonaws.auth.AWSStaticCredentialsProvider -import com.amazonaws.auth.AnonymousAWSCredentials -import com.amazonaws.auth.BasicAWSCredentials -import com.amazonaws.auth.EnvironmentVariableCredentialsProvider -import com.amazonaws.auth.InstanceProfileCredentialsProvider -import com.amazonaws.auth.SystemPropertiesCredentialsProvider -import com.amazonaws.auth.profile.ProfileCredentialsProvider -import com.amazonaws.client.builder.AwsClientBuilder -import com.amazonaws.handlers.RequestHandler2 -import com.amazonaws.regions.Regions -import com.amazonaws.retry.PredefinedRetryPolicies -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest -import com.amazonaws.services.ec2.AmazonEC2ClientBuilder -import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder -import com.amazonaws.services.kinesis.model.DeleteStreamRequest -import com.amazonaws.services.rds.AmazonRDSClientBuilder -import com.amazonaws.services.rds.model.DeleteOptionGroupRequest -import com.amazonaws.services.s3.AmazonS3Client -import com.amazonaws.services.s3.AmazonS3ClientBuilder -import com.amazonaws.services.sqs.AmazonSQSClientBuilder -import com.amazonaws.services.sqs.model.CreateQueueRequest -import com.amazonaws.services.sqs.model.SendMessageRequest -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.atomic.AtomicReference -import spock.lang.AutoCleanup -import spock.lang.Shared - -class Aws1ClientTest extends AgentTestRunner { - - private static final CREDENTIALS_PROVIDER_CHAIN = new AWSCredentialsProviderChain( - new EnvironmentVariableCredentialsProvider(), - new SystemPropertiesCredentialsProvider(), - new ProfileCredentialsProvider(), - new InstanceProfileCredentialsProvider()) - - def setupSpec() { - System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key") - System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key") - } - - def cleanupSpec() { - System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY) - System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY) - } - - @Shared - def credentialsProvider = new AWSStaticCredentialsProvider(new AnonymousAWSCredentials()) - @Shared - def responseBody = new AtomicReference() - @AutoCleanup - @Shared - def server = httpServer { - handlers { - all { - response.status(200).send(responseBody.get()) - } - } - } - @Shared - def endpoint = new AwsClientBuilder.EndpointConfiguration("http://localhost:$server.address.port", "us-west-2") - - def "request handler is hooked up with builder"() { - setup: - def builder = AmazonS3ClientBuilder.standard() - .withRegion(Regions.US_EAST_1) - if (addHandler) { - builder.withRequestHandlers(new RequestHandler2() {}) - } - AmazonWebServiceClient client = builder.build() - - expect: - client.requestHandler2s != null - client.requestHandler2s.size() == size - client.requestHandler2s.get(position).getClass().getSimpleName() == "TracingRequestHandler" - - where: - addHandler | size | position - true | 2 | 1 - false | 1 | 0 - } - - def "request handler is hooked up with constructor"() { - setup: - String accessKey = "asdf" - String secretKey = "qwerty" - def credentials = new BasicAWSCredentials(accessKey, secretKey) - def client = new AmazonS3Client(credentials) - if (addHandler) { - client.addRequestHandler(new RequestHandler2() {}) - } - - expect: - client.requestHandler2s != null - client.requestHandler2s.size() == size - client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler" - - where: - addHandler | size - true | 2 - false | 1 - } - - def "send #operation request with mocked response"() { - setup: - responseBody.set(body) - - when: - def response = call.call(client) - - then: - response != null - - client.requestHandler2s != null - client.requestHandler2s.size() == handlerCount - client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "$service.$operation" - kind CLIENT - errored false - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "$server.address" - "${SemanticAttributes.HTTP_METHOD.key()}" "$method" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "aws.service" { it.contains(service) } - "aws.endpoint" "$server.address" - "aws.operation" "${operation}Request" - "aws.agent" "java-aws-sdk" - for (def addedTag : additionalAttributes) { - "$addedTag.key" "$addedTag.value" - } - } - } - } - } - server.lastRequest.headers.get("traceparent") != null - - where: - service | operation | method | path | handlerCount | client | call | additionalAttributes | body - "S3" | "CreateBucket" | "PUT" | "/testbucket/" | 1 | AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true).withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { client -> client.createBucket("testbucket") } | ["aws.bucket.name": "testbucket"] | "" - "S3" | "GetObject" | "GET" | "/someBucket/someKey" | 1 | AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true).withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { client -> client.getObject("someBucket", "someKey") } | ["aws.bucket.name": "someBucket"] | "" - "DynamoDBv2" | "CreateTable" | "POST" | "/" | 1 | AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { c -> c.createTable(new CreateTableRequest("sometable", null)) } | ["aws.table.name": "sometable"] | "" - "Kinesis" | "DeleteStream" | "POST" | "/" | 1 | AmazonKinesisClientBuilder.standard().withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { c -> c.deleteStream(new DeleteStreamRequest().withStreamName("somestream")) } | ["aws.stream.name": "somestream"] | "" - "SQS" | "CreateQueue" | "POST" | "/" | 4 | AmazonSQSClientBuilder.standard().withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { c -> c.createQueue(new CreateQueueRequest("somequeue")) } | ["aws.queue.name": "somequeue"] | """ - - https://queue.amazonaws.com/123456789012/MyQueue - 7a62c49f-347e-4fc4-9331-6e8e7a96aa73 - - """ - "SQS" | "SendMessage" | "POST" | "/someurl" | 4 | AmazonSQSClientBuilder.standard().withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { c -> c.sendMessage(new SendMessageRequest("someurl", "")) } | ["aws.queue.url": "someurl"] | """ - - - d41d8cd98f00b204e9800998ecf8427e - 3ae8f24a165a8cedc005670c81a27295 - 5fea7756-0ea4-451a-a703-a558b933e274 - - 27daac76-34dd-47df-bd01-1f6e873584a0 - - """ - "EC2" | "AllocateAddress" | "POST" | "/" | 4 | AmazonEC2ClientBuilder.standard().withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { client -> client.allocateAddress() } | [:] | """ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - 192.0.2.1 - standard - - """ - "RDS" | "DeleteOptionGroup" | "POST" | "/" | 5 | AmazonRDSClientBuilder.standard().withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build() | { client -> client.deleteOptionGroup(new DeleteOptionGroupRequest()) } | [:] | """ - - - 0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99 - - - """ - } - - def "send #operation request to closed port"() { - setup: - responseBody.set(body) - - when: - call.call(client) - - then: - thrown SdkClientException - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "$service.$operation" - kind CLIENT - errored true - errorEvent SdkClientException, ~/Unable to execute HTTP request/ - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:${UNUSABLE_PORT}" - "${SemanticAttributes.HTTP_METHOD.key()}" "$method" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" 61 - "aws.service" { it.contains(service) } - "aws.endpoint" "http://localhost:${UNUSABLE_PORT}" - "aws.operation" "${operation}Request" - "aws.agent" "java-aws-sdk" - for (def addedTag : additionalAttributes) { - "$addedTag.key" "$addedTag.value" - } - } - } - } - } - - where: - service | operation | method | url | call | additionalAttributes | body | client - "S3" | "GetObject" | "GET" | "someBucket/someKey" | { client -> client.getObject("someBucket", "someKey") } | ["aws.bucket.name": "someBucket"] | "" | new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN, new ClientConfiguration().withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0))).withEndpoint("http://localhost:${UNUSABLE_PORT}") - } - - def "naughty request handler doesn't break the trace"() { - setup: - def client = new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN) - client.addRequestHandler(new RequestHandler2() { - void beforeRequest(Request request) { - throw new RuntimeException("bad handler") - } - }) - - when: - client.getObject("someBucket", "someKey") - - then: - !Span.current().getSpanContext().isValid() - thrown RuntimeException - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "S3.HeadBucket" - kind CLIENT - errored true - errorEvent RuntimeException, "bad handler" - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "https://s3.amazonaws.com" - "${SemanticAttributes.HTTP_METHOD.key()}" "HEAD" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_NAME.key()}" "s3.amazonaws.com" - "aws.service" "Amazon S3" - "aws.endpoint" "https://s3.amazonaws.com" - "aws.operation" "HeadBucketRequest" - "aws.agent" "java-aws-sdk" - } - } - } - } - } - - // TODO(anuraaga): Add events for retries. - def "timeout and retry errors not captured"() { - setup: - def server = httpServer { - handlers { - all { - Thread.sleep(500) - response.status(200).send() - } - } - } - AmazonS3Client client = new AmazonS3Client(new ClientConfiguration().withRequestTimeout(50 /* ms */)) - .withEndpoint("http://localhost:$server.address.port") - - when: - client.getObject("someBucket", "someKey") - - then: - !Span.current().getSpanContext().isValid() - thrown AmazonClientException - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "S3.GetObject" - kind CLIENT - errored true - try { - errorEvent AmazonClientException, ~/Unable to execute HTTP request/ - } catch (AssertionError e) { - errorEvent SdkClientException, "Unable to execute HTTP request: Request did not complete before the request timeout configuration." - } - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "$server.address" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "aws.service" "Amazon S3" - "aws.endpoint" "$server.address" - "aws.operation" "GetObjectRequest" - "aws.agent" "java-aws-sdk" - "aws.bucket.name" "someBucket" - } - } - } - } - - cleanup: - server.close() - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/src/test_before_1_11_106/groovy/Aws0ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/src/test_before_1_11_106/groovy/Aws0ClientTest.groovy deleted file mode 100644 index b1b54120da..0000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/src/test_before_1_11_106/groovy/Aws0ClientTest.groovy +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.server.http.TestHttpServer.httpServer -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT - -import com.amazonaws.AmazonClientException -import com.amazonaws.ClientConfiguration -import com.amazonaws.Request -import com.amazonaws.SDKGlobalConfiguration -import com.amazonaws.auth.AWSCredentialsProviderChain -import com.amazonaws.auth.BasicAWSCredentials -import com.amazonaws.auth.EnvironmentVariableCredentialsProvider -import com.amazonaws.auth.InstanceProfileCredentialsProvider -import com.amazonaws.auth.SystemPropertiesCredentialsProvider -import com.amazonaws.auth.profile.ProfileCredentialsProvider -import com.amazonaws.handlers.RequestHandler2 -import com.amazonaws.retry.PredefinedRetryPolicies -import com.amazonaws.services.ec2.AmazonEC2Client -import com.amazonaws.services.rds.AmazonRDSClient -import com.amazonaws.services.rds.model.DeleteOptionGroupRequest -import com.amazonaws.services.s3.AmazonS3Client -import com.amazonaws.services.s3.S3ClientOptions -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.atomic.AtomicReference -import spock.lang.AutoCleanup -import spock.lang.Shared - -class Aws0ClientTest extends AgentTestRunner { - - private static final CREDENTIALS_PROVIDER_CHAIN = new AWSCredentialsProviderChain( - new EnvironmentVariableCredentialsProvider(), - new SystemPropertiesCredentialsProvider(), - new ProfileCredentialsProvider(), - new InstanceProfileCredentialsProvider()) - - def setupSpec() { - System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key") - System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key") - } - - def cleanupSpec() { - System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY) - System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY) - } - - @Shared - def responseBody = new AtomicReference() - @AutoCleanup - @Shared - def server = httpServer { - handlers { - all { - response.status(200).send(responseBody.get()) - } - } - } - - def "request handler is hooked up with constructor"() { - setup: - String accessKey = "asdf" - String secretKey = "qwerty" - def credentials = new BasicAWSCredentials(accessKey, secretKey) - def client = new AmazonS3Client(credentials) - if (addHandler) { - client.addRequestHandler(new RequestHandler2() {}) - } - - expect: - client.requestHandler2s != null - client.requestHandler2s.size() == size - client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler" - - where: - addHandler | size - true | 2 - false | 1 - } - - def "send #operation request with mocked response"() { - setup: - responseBody.set(body) - - when: - def response = call.call(client) - - then: - response != null - - client.requestHandler2s != null - client.requestHandler2s.size() == handlerCount - client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "$service.$operation" - kind CLIENT - errored false - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "$server.address" - "${SemanticAttributes.HTTP_METHOD.key()}" "$method" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "aws.service" { it.contains(service) } - "aws.endpoint" "$server.address" - "aws.operation" "${operation}Request" - "aws.agent" "java-aws-sdk" - for (def addedTag : additionalAttributes) { - "$addedTag.key" "$addedTag.value" - } - } - } - } - } - server.lastRequest.headers.get("traceparent") != null - - where: - service | operation | method | path | handlerCount | client | additionalAttributes | call | body - "S3" | "CreateBucket" | "PUT" | "/testbucket/" | 1 | new AmazonS3Client().withEndpoint("http://localhost:$server.address.port") | ["aws.bucket.name": "testbucket"] | { client -> client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build()); client.createBucket("testbucket") } | "" - "S3" | "GetObject" | "GET" | "/someBucket/someKey" | 1 | new AmazonS3Client().withEndpoint("http://localhost:$server.address.port") | ["aws.bucket.name": "someBucket"] | { client -> client.getObject("someBucket", "someKey") } | "" - "EC2" | "AllocateAddress" | "POST" | "/" | 4 | new AmazonEC2Client().withEndpoint("http://localhost:$server.address.port") | [:] | { client -> client.allocateAddress() } | """ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - 192.0.2.1 - standard - - """ - "RDS" | "DeleteOptionGroup" | "POST" | "/" | 1 | new AmazonRDSClient().withEndpoint("http://localhost:$server.address.port") | [:] | { client -> client.deleteOptionGroup(new DeleteOptionGroupRequest()) } | """ - - - 0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99 - - - """ - } - - def "send #operation request to closed port"() { - setup: - responseBody.set(body) - - when: - call.call(client) - - then: - thrown AmazonClientException - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "$service.$operation" - kind CLIENT - errored true - errorEvent AmazonClientException, ~/Unable to execute HTTP request/ - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:${UNUSABLE_PORT}" - "${SemanticAttributes.HTTP_METHOD.key()}" "$method" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" 61 - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "aws.service" { it.contains(service) } - "aws.endpoint" "http://localhost:${UNUSABLE_PORT}" - "aws.operation" "${operation}Request" - "aws.agent" "java-aws-sdk" - for (def addedTag : additionalAttributes) { - "$addedTag.key" "$addedTag.value" - } - } - } - } - } - - where: - service | operation | method | url | call | additionalAttributes | body | client - "S3" | "GetObject" | "GET" | "someBucket/someKey" | { client -> client.getObject("someBucket", "someKey") } | ["aws.bucket.name": "someBucket"] | "" | new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN, new ClientConfiguration().withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0))).withEndpoint("http://localhost:${UNUSABLE_PORT}") - } - - def "naughty request handler doesn't break the trace"() { - setup: - def client = new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN) - client.addRequestHandler(new RequestHandler2() { - void beforeRequest(Request request) { - throw new RuntimeException("bad handler") - } - }) - - when: - client.getObject("someBucket", "someKey") - - then: - !Span.current().getSpanContext().isValid() - thrown RuntimeException - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "S3.GetObject" - kind CLIENT - errored true - errorEvent RuntimeException, "bad handler" - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "https://s3.amazonaws.com" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_NAME.key()}" "s3.amazonaws.com" - "aws.service" "Amazon S3" - "aws.endpoint" "https://s3.amazonaws.com" - "aws.operation" "GetObjectRequest" - "aws.agent" "java-aws-sdk" - "aws.bucket.name" "someBucket" - } - } - } - } - } - - // TODO(anuraaga): Add events for retries. - def "timeout and retry errors not captured"() { - setup: - def server = httpServer { - handlers { - all { - Thread.sleep(500) - response.status(200).send() - } - } - } - AmazonS3Client client = new AmazonS3Client(new ClientConfiguration().withRequestTimeout(50 /* ms */)) - .withEndpoint("http://localhost:$server.address.port") - - when: - client.getObject("someBucket", "someKey") - - then: - !Span.current().getSpanContext().isValid() - thrown AmazonClientException - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "S3.GetObject" - kind CLIENT - errored true - errorEvent AmazonClientException, ~/Unable to execute HTTP request/ - hasNoParent() - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "$server.address" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "aws.service" "Amazon S3" - "aws.endpoint" "http://localhost:$server.address.port" - "aws.operation" "GetObjectRequest" - "aws.agent" "java-aws-sdk" - "aws.bucket.name" "someBucket" - } - } - } - } - - cleanup: - server.close() - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/cassandra/cassandra-3.0/cassandra-3.0.gradle b/instrumentation/cassandra/cassandra-3.0/cassandra-3.0.gradle deleted file mode 100644 index 7270f3f646..0000000000 --- a/instrumentation/cassandra/cassandra-3.0/cassandra-3.0.gradle +++ /dev/null @@ -1,43 +0,0 @@ -// Set properties before any plugins get loaded -ext { - cassandraDriverTestVersions = "[3.0,4.0)" -} - -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - - pass { - group = "com.datastax.cassandra" - module = "cassandra-driver-core" - versions = cassandraDriverTestVersions - assertInverse = true - // Older versions of cassandra-driver-core require an older guava dependency (0.16.0). guava >20.0 is not - // compatible with Java 7, so we declare the dependency on 20.0 in our top level dependencies.gradle. - // Ideally our muzzle plugin should take into account those versions declaration, instead it does not so we would - // end up with testing compatibility with guava 0.16 which lacks the method invocation added to be compatible with - // most recent versions of guava (27+). While the long term solution is to make the muzzle plugin aware of upstream - // declared dependencies, for now we just make sure that we use the proper ones. - extraDependency "com.google.guava:guava:20.0" - } - - // Making sure that instrumentation works with recent versions of Guava which removed method - // Futures::transform(input, function) in favor of Futures::transform(input, function, executor) - pass { - name = "Newest versions of Guava" - group = "com.datastax.cassandra" - module = "cassandra-driver-core" - versions = cassandraDriverTestVersions - // While com.datastax.cassandra uses old versions of Guava, users may depends themselves on newer versions of Guava - extraDependency "com.google.guava:guava:27.0-jre" - } -} - -dependencies { - library group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.0.0' - - testLibrary group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.2.0' - testImplementation project(':instrumentation:guava-10.0') - - latestDepTestLibrary group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.+' -} diff --git a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraClientInstrumentationModule.java b/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraClientInstrumentationModule.java deleted file mode 100644 index 0c59cec9c4..0000000000 --- a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraClientInstrumentationModule.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -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.takesArguments; - -import com.datastax.driver.core.Session; -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class CassandraClientInstrumentationModule extends InstrumentationModule { - public CassandraClientInstrumentationModule() { - super("cassandra", "cassandra-3.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ClusterManagerInstrumentation()); - } - - public static class ClusterManagerInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - // Note: Cassandra has a large driver and we instrument single class in it. - // The rest is ignored in AdditionalLibraryIgnoresMatcher - return named("com.datastax.driver.core.Cluster$Manager"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPrivate()).and(named("newSession")).and(takesArguments(0)), - CassandraClientInstrumentationModule.class.getName() + "$CassandraClientAdvice"); - } - } - - public static class CassandraClientAdvice { - /** - * Strategy: each time we build a connection to a Cassandra cluster, the - * com.datastax.driver.core.Cluster$Manager.newSession() method is called. The opentracing - * contribution is a simple wrapper, so we just have to wrap the new session. - * - * @param session The fresh session to patch. This session is replaced with new session - */ - @Advice.OnMethodExit(suppress = Throwable.class) - public static void injectTracingSession(@Advice.Return(readOnly = false) Session session) { - // This should cover ours and OT's TracingSession - if (session.getClass().getName().endsWith("cassandra.TracingSession")) { - return; - } - session = new TracingSession(session); - } - } -} diff --git a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java b/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java deleted file mode 100644 index 83f859a833..0000000000 --- a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraDatabaseClientTracer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0; - -import com.datastax.driver.core.ExecutionInfo; -import com.datastax.driver.core.Host; -import com.datastax.driver.core.Session; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.net.InetSocketAddress; - -public class CassandraDatabaseClientTracer extends DatabaseClientTracer { - private static final CassandraDatabaseClientTracer TRACER = new CassandraDatabaseClientTracer(); - - public static CassandraDatabaseClientTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.cassandra"; - } - - @Override - protected String normalizeQuery(String query) { - return CassandraQueryNormalizer.normalize(query); - } - - @Override - protected String dbSystem(Session session) { - return DbSystem.CASSANDRA; - } - - @Override - protected String dbName(Session session) { - return session.getLoggedKeyspace(); - } - - @Override - protected Span onConnection(Span span, Session session) { - span.setAttribute(SemanticAttributes.DB_CASSANDRA_KEYSPACE, session.getLoggedKeyspace()); - return super.onConnection(span, session); - } - - @Override - protected InetSocketAddress peerAddress(Session session) { - return null; - } - - public void end(Span span, ExecutionInfo executionInfo) { - Host host = executionInfo.getQueriedHost(); - NetPeerUtils.setNetPeer(span, host.getSocketAddress()); - end(span); - } -} diff --git a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraQueryNormalizer.java b/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraQueryNormalizer.java deleted file mode 100644 index 8b84f5e7dd..0000000000 --- a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraQueryNormalizer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0; - -import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled; - -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CassandraQueryNormalizer { - private static final Logger log = LoggerFactory.getLogger(CassandraQueryNormalizer.class); - private static final boolean NORMALIZATION_ENABLED = - isQueryNormalizationEnabled("cassandra", "cassandra-3.0"); - - public static String normalize(String query) { - if (!NORMALIZATION_ENABLED) { - return query; - } - try { - return SqlNormalizer.normalize(query); - } catch (ParseException e) { - log.debug("Could not normalize Cassandra query", e); - return null; - } - } - - private CassandraQueryNormalizer() {} -} diff --git a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/TracingSession.java b/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/TracingSession.java deleted file mode 100644 index e92fecd6da..0000000000 --- a/instrumentation/cassandra/cassandra-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/TracingSession.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0; - -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; -import static io.opentelemetry.javaagent.instrumentation.cassandra.v3_0.CassandraDatabaseClientTracer.tracer; - -import com.datastax.driver.core.BoundStatement; -import com.datastax.driver.core.CloseFuture; -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.PreparedStatement; -import com.datastax.driver.core.RegularStatement; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.ResultSetFuture; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.Statement; -import com.google.common.base.Function; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.util.Map; - -public class TracingSession implements Session { - - private final Session session; - - public TracingSession(Session session) { - this.session = session; - } - - @Override - public String getLoggedKeyspace() { - return session.getLoggedKeyspace(); - } - - @Override - public Session init() { - return new TracingSession(session.init()); - } - - @Override - public ListenableFuture initAsync() { - return Futures.transform( - session.initAsync(), - new Function() { - @Override - public Session apply(Session session) { - return new TracingSession(session); - } - }, - directExecutor()); - } - - @Override - public ResultSet execute(String query) { - Span span = tracer().startSpan(session, query); - ResultSet resultSet; - try (Scope ignored = tracer().startScope(span)) { - resultSet = session.execute(query); - } catch (Throwable t) { - tracer().endExceptionally(span, t); - throw t; - } - tracer().end(span, resultSet.getExecutionInfo()); - return resultSet; - } - - @Override - public ResultSet execute(String query, Object... values) { - Span span = tracer().startSpan(session, query); - ResultSet resultSet; - try (Scope ignored = tracer().startScope(span)) { - resultSet = session.execute(query, values); - } catch (Throwable t) { - tracer().endExceptionally(span, t); - throw t; - } - tracer().end(span, resultSet.getExecutionInfo()); - return resultSet; - } - - @Override - public ResultSet execute(String query, Map values) { - Span span = tracer().startSpan(session, query); - ResultSet resultSet; - try (Scope ignored = tracer().startScope(span)) { - resultSet = session.execute(query, values); - } catch (Throwable t) { - tracer().endExceptionally(span, t); - throw t; - } - tracer().end(span, resultSet.getExecutionInfo()); - return resultSet; - } - - @Override - public ResultSet execute(Statement statement) { - Span span = tracer().startSpan(session, getQuery(statement)); - ResultSet resultSet; - try (Scope ignored = tracer().startScope(span)) { - resultSet = session.execute(statement); - } catch (Throwable t) { - tracer().endExceptionally(span, t); - throw t; - } - tracer().end(span, resultSet.getExecutionInfo()); - return resultSet; - } - - @Override - public ResultSetFuture executeAsync(String query) { - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - ResultSetFuture future = session.executeAsync(query); - addCallbackToEndSpan(future, span); - return future; - } - } - - @Override - public ResultSetFuture executeAsync(String query, Object... values) { - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - ResultSetFuture future = session.executeAsync(query, values); - addCallbackToEndSpan(future, span); - return future; - } - } - - @Override - public ResultSetFuture executeAsync(String query, Map values) { - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - ResultSetFuture future = session.executeAsync(query, values); - addCallbackToEndSpan(future, span); - return future; - } - } - - @Override - public ResultSetFuture executeAsync(Statement statement) { - String query = getQuery(statement); - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - ResultSetFuture future = session.executeAsync(statement); - addCallbackToEndSpan(future, span); - return future; - } - } - - @Override - public PreparedStatement prepare(String query) { - return session.prepare(query); - } - - @Override - public PreparedStatement prepare(RegularStatement statement) { - return session.prepare(statement); - } - - @Override - public ListenableFuture prepareAsync(String query) { - return session.prepareAsync(query); - } - - @Override - public ListenableFuture prepareAsync(RegularStatement statement) { - return session.prepareAsync(statement); - } - - @Override - public CloseFuture closeAsync() { - return session.closeAsync(); - } - - @Override - public void close() { - session.close(); - } - - @Override - public boolean isClosed() { - return session.isClosed(); - } - - @Override - public Cluster getCluster() { - return session.getCluster(); - } - - @Override - public State getState() { - return session.getState(); - } - - private static String getQuery(Statement statement) { - String query = null; - if (statement instanceof BoundStatement) { - query = ((BoundStatement) statement).preparedStatement().getQueryString(); - } else if (statement instanceof RegularStatement) { - query = ((RegularStatement) statement).getQueryString(); - } - - return query == null ? "" : query; - } - - private void addCallbackToEndSpan(ResultSetFuture future, final Span span) { - Futures.addCallback( - future, - new FutureCallback() { - @Override - public void onSuccess(ResultSet result) { - tracer().end(span, result.getExecutionInfo()); - } - - @Override - public void onFailure(Throwable t) { - tracer().endExceptionally(span, t); - } - }, - directExecutor()); - } -} diff --git a/instrumentation/cassandra/cassandra-3.0/src/test/groovy/CassandraClientTest.groovy b/instrumentation/cassandra/cassandra-3.0/src/test/groovy/CassandraClientTest.groovy deleted file mode 100644 index 1e6ac19945..0000000000 --- a/instrumentation/cassandra/cassandra-3.0/src/test/groovy/CassandraClientTest.groovy +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.datastax.driver.core.Cluster -import com.datastax.driver.core.Session -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.sdk.trace.data.SpanData -import java.time.Duration -import java.util.concurrent.Executors -import java.util.concurrent.atomic.AtomicBoolean -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.testcontainers.containers.GenericContainer -import org.testcontainers.containers.output.Slf4jLogConsumer -import spock.lang.Shared - -class CassandraClientTest extends AgentTestRunner { - private static final Logger log = LoggerFactory.getLogger(CassandraClientTest) - - @Shared - def executor = Executors.newCachedThreadPool() - - @Shared - GenericContainer cassandra - @Shared - int cassandraPort - @Shared - Cluster cluster - - def setupSpec() { - cassandra = new GenericContainer("cassandra:3") - .withExposedPorts(9042) - .withLogConsumer(new Slf4jLogConsumer(log)) - .withStartupTimeout(Duration.ofSeconds(120)) - cassandra.start() - - cassandraPort = cassandra.getMappedPort(9042) - - cluster = Cluster.builder() - .addContactPointsWithPorts(new InetSocketAddress("localhost", cassandraPort)) - .build() - } - - def cleanupSpec() { - cluster.close() - cassandra.stop() - } - - def "test sync"() { - setup: - Session session = cluster.connect(keyspace) - - session.execute(statement) - - expect: - assertTraces(keyspace ? 2 : 1) { - if (keyspace) { - trace(0, 1) { - cassandraSpan(it, 0, "USE $keyspace", null) - } - } - trace(keyspace ? 1 : 0, 1) { - cassandraSpan(it, 0, expectedStatement, keyspace) - } - } - - cleanup: - session.close() - - where: - keyspace | statement | expectedStatement - null | "DROP KEYSPACE IF EXISTS sync_test" | "DROP KEYSPACE IF EXISTS sync_test" - null | "CREATE KEYSPACE sync_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}" | "CREATE KEYSPACE sync_test WITH REPLICATION = {?:?, ?:?}" - "sync_test" | "CREATE TABLE sync_test.users ( id UUID PRIMARY KEY, name text )" | "CREATE TABLE sync_test.users ( id UUID PRIMARY KEY, name text )" - "sync_test" | "INSERT INTO sync_test.users (id, name) values (uuid(), 'alice')" | "INSERT INTO sync_test.users (id, name) values (uuid(), ?)" - "sync_test" | "SELECT * FROM users where name = 'alice' ALLOW FILTERING" | "SELECT * FROM users where name = ? ALLOW FILTERING" - } - - def "test async"() { - setup: - def callbackExecuted = new AtomicBoolean() - Session session = cluster.connect(keyspace) - runUnderTrace("parent") { - def future = session.executeAsync(statement) - future.addListener({ -> - runUnderTrace("callbackListener") { - callbackExecuted.set(true) - } - }, executor) - } - - expect: - assertTraces(keyspace ? 2 : 1) { - if (keyspace) { - trace(0, 1) { - cassandraSpan(it, 0, "USE $keyspace", null) - } - } - trace(keyspace ? 1 : 0, 3) { - basicSpan(it, 0, "parent") - cassandraSpan(it, 1, expectedStatement, keyspace, span(0)) - basicSpan(it, 2, "callbackListener", span(0)) - } - } - - cleanup: - session.close() - - where: - keyspace | statement | expectedStatement - null | "DROP KEYSPACE IF EXISTS async_test" | "DROP KEYSPACE IF EXISTS async_test" - null | "CREATE KEYSPACE async_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}" | "CREATE KEYSPACE async_test WITH REPLICATION = {?:?, ?:?}" - "async_test" | "CREATE TABLE async_test.users ( id UUID PRIMARY KEY, name text )" | "CREATE TABLE async_test.users ( id UUID PRIMARY KEY, name text )" - "async_test" | "INSERT INTO async_test.users (id, name) values (uuid(), 'alice')" | "INSERT INTO async_test.users (id, name) values (uuid(), ?)" - "async_test" | "SELECT * FROM users where name = 'alice' ALLOW FILTERING" | "SELECT * FROM users where name = ? ALLOW FILTERING" - } - - def cassandraSpan(TraceAssert trace, int index, String statement, String keyspace, Object parentSpan = null, Throwable exception = null) { - trace.span(index) { - name statement - kind CLIENT - if (parentSpan == null) { - hasNoParent() - } else { - childOf((SpanData) parentSpan) - } - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_PORT.key" cassandraPort - "$SemanticAttributes.DB_SYSTEM.key" "cassandra" - "$SemanticAttributes.DB_NAME.key" keyspace - "$SemanticAttributes.DB_STATEMENT.key" statement - "$SemanticAttributes.DB_CASSANDRA_KEYSPACE.key" keyspace - } - } - } -} diff --git a/instrumentation/cassandra/cassandra-4.0/cassandra-4.0.gradle b/instrumentation/cassandra/cassandra-4.0/cassandra-4.0.gradle deleted file mode 100644 index 79e0bec1c2..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/cassandra-4.0.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.datastax.oss" - module = "java-driver-core" - versions = "[4.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'com.datastax.oss', name: 'java-driver-core', version: '4.0.0' - - latestDepTestLibrary group: 'com.datastax.oss', name: 'java-driver-core', version: '4.+' -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraClientAdvice.java b/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraClientAdvice.java deleted file mode 100644 index 01f0710425..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraClientAdvice.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; - -import java.util.concurrent.CompletionStage; -import net.bytebuddy.asm.Advice; - -public class CassandraClientAdvice { - /** - * Strategy: each time we build a connection to a Cassandra cluster, the - * com.datastax.oss.driver.api.core.session.SessionBuilder.buildAsync() method is called. The - * opentracing contribution is a simple wrapper, so we just have to wrap the new session. - * - * @param stage The fresh CompletionStage to patch. This stage produces session which is replaced - * with new session - */ - @Advice.OnMethodExit(suppress = Throwable.class) - public static void injectTracingSession( - @Advice.Return(readOnly = false) CompletionStage stage) { - stage = stage.thenApply(new CompletionStageFunction()); - } -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraClientInstrumentationModule.java b/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraClientInstrumentationModule.java deleted file mode 100644 index ca4924aa2a..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraClientInstrumentationModule.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class CassandraClientInstrumentationModule extends InstrumentationModule { - public CassandraClientInstrumentationModule() { - super("cassandra", "cassandra-4.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new SessionBuilderInstrumentation()); - } - - public static class SessionBuilderInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - // Note: Cassandra has a large driver and we instrument single class in it. - // The rest is ignored in AdditionalLibraryIgnoresMatcher - return named("com.datastax.oss.driver.api.core.session.SessionBuilder"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("buildAsync")).and(takesArguments(0)), - CassandraClientAdvice.class.getName()); - } - } -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraDatabaseClientTracer.java b/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraDatabaseClientTracer.java deleted file mode 100644 index 57d0c393f8..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraDatabaseClientTracer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; - -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.cql.ExecutionInfo; -import com.datastax.oss.driver.api.core.metadata.Node; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -public class CassandraDatabaseClientTracer extends DatabaseClientTracer { - private static final CassandraDatabaseClientTracer TRACER = new CassandraDatabaseClientTracer(); - - public static CassandraDatabaseClientTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.cassandra"; - } - - @Override - protected String normalizeQuery(String query) { - return CassandraQueryNormalizer.normalize(query); - } - - @Override - protected String dbSystem(CqlSession session) { - return DbSystem.CASSANDRA; - } - - @Override - protected String dbName(CqlSession session) { - return session.getKeyspace().map(CqlIdentifier::toString).orElse(null); - } - - @Override - protected InetSocketAddress peerAddress(CqlSession cqlSession) { - return null; - } - - public void onResponse(Span span, ExecutionInfo executionInfo) { - Node coordinator = executionInfo.getCoordinator(); - if (coordinator != null) { - SocketAddress socketAddress = coordinator.getEndPoint().resolve(); - if (socketAddress instanceof InetSocketAddress) { - NetPeerUtils.setNetPeer(span, ((InetSocketAddress) socketAddress)); - } - } - } -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraQueryNormalizer.java b/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraQueryNormalizer.java deleted file mode 100644 index d462814d6e..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraQueryNormalizer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled; - -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CassandraQueryNormalizer { - private static final Logger log = LoggerFactory.getLogger(CassandraQueryNormalizer.class); - private static final boolean NORMALIZATION_ENABLED = - isQueryNormalizationEnabled("cassandra", "cassandra-4.0"); - - public static String normalize(String query) { - if (!NORMALIZATION_ENABLED) { - return query; - } - try { - return SqlNormalizer.normalize(query); - } catch (ParseException e) { - log.debug("Could not normalize Cassandra query", e); - return null; - } - } - - private CassandraQueryNormalizer() {} -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CompletionStageFunction.java b/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CompletionStageFunction.java deleted file mode 100644 index 14aa73c849..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CompletionStageFunction.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; - -import com.datastax.oss.driver.api.core.CqlSession; -import java.util.function.Function; - -public class CompletionStageFunction implements Function { - - @Override - public Object apply(Object session) { - if (session == null) { - return null; - } - // This should cover ours and OT's TracingCqlSession - if (session.getClass().getName().endsWith("cassandra4.TracingCqlSession")) { - return session; - } - return new TracingCqlSession((CqlSession) session); - } -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/TracingCqlSession.java b/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/TracingCqlSession.java deleted file mode 100644 index c8c1a33542..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/TracingCqlSession.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.cassandra.v4_0.CassandraDatabaseClientTracer.tracer; - -import com.datastax.oss.driver.api.core.CqlIdentifier; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.context.DriverContext; -import com.datastax.oss.driver.api.core.cql.AsyncResultSet; -import com.datastax.oss.driver.api.core.cql.BoundStatement; -import com.datastax.oss.driver.api.core.cql.PrepareRequest; -import com.datastax.oss.driver.api.core.cql.PreparedStatement; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import com.datastax.oss.driver.api.core.cql.SimpleStatement; -import com.datastax.oss.driver.api.core.cql.Statement; -import com.datastax.oss.driver.api.core.metadata.Metadata; -import com.datastax.oss.driver.api.core.metrics.Metrics; -import com.datastax.oss.driver.api.core.session.Request; -import com.datastax.oss.driver.api.core.type.reflect.GenericType; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.util.Optional; -import java.util.concurrent.CompletionStage; - -public class TracingCqlSession implements CqlSession { - private final CqlSession session; - - public TracingCqlSession(CqlSession session) { - this.session = session; - } - - @Override - @NonNull - public PreparedStatement prepare(@NonNull SimpleStatement statement) { - return session.prepare(statement); - } - - @Override - @NonNull - public PreparedStatement prepare(@NonNull String query) { - return session.prepare(query); - } - - @Override - @NonNull - public PreparedStatement prepare(@NonNull PrepareRequest request) { - return session.prepare(request); - } - - @Override - @NonNull - public CompletionStage prepareAsync(@NonNull SimpleStatement statement) { - return session.prepareAsync(statement); - } - - @Override - @NonNull - public CompletionStage prepareAsync(@NonNull String query) { - return session.prepareAsync(query); - } - - @Override - @NonNull - public CompletionStage prepareAsync(PrepareRequest request) { - return session.prepareAsync(request); - } - - @Override - @NonNull - public String getName() { - return session.getName(); - } - - @Override - @NonNull - public Metadata getMetadata() { - return session.getMetadata(); - } - - @Override - public boolean isSchemaMetadataEnabled() { - return session.isSchemaMetadataEnabled(); - } - - @Override - @NonNull - public CompletionStage setSchemaMetadataEnabled(@Nullable Boolean newValue) { - return session.setSchemaMetadataEnabled(newValue); - } - - @Override - @NonNull - public CompletionStage refreshSchemaAsync() { - return session.refreshSchemaAsync(); - } - - @Override - @NonNull - public Metadata refreshSchema() { - return session.refreshSchema(); - } - - @Override - @NonNull - public CompletionStage checkSchemaAgreementAsync() { - return session.checkSchemaAgreementAsync(); - } - - @Override - public boolean checkSchemaAgreement() { - return session.checkSchemaAgreement(); - } - - @Override - @NonNull - public DriverContext getContext() { - return session.getContext(); - } - - @Override - @NonNull - public Optional getKeyspace() { - return session.getKeyspace(); - } - - @Override - @NonNull - public Optional getMetrics() { - return session.getMetrics(); - } - - @Override - @NonNull - public CompletionStage closeFuture() { - return session.closeFuture(); - } - - @Override - public boolean isClosed() { - return session.isClosed(); - } - - @Override - @NonNull - public CompletionStage closeAsync() { - return session.closeAsync(); - } - - @Override - @NonNull - public CompletionStage forceCloseAsync() { - return session.forceCloseAsync(); - } - - @Override - public void close() { - session.close(); - } - - @Override - @Nullable - public RESULT execute( - @NonNull REQUEST request, @NonNull GenericType resultType) { - return session.execute(request, resultType); - } - - @Override - @NonNull - public ResultSet execute(@NonNull String query) { - - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - try { - ResultSet resultSet = session.execute(query); - tracer().onResponse(span, resultSet.getExecutionInfo()); - return resultSet; - } catch (RuntimeException e) { - tracer().endExceptionally(span, e); - throw e; - } finally { - tracer().end(span); - } - } - } - - @Override - @NonNull - public ResultSet execute(@NonNull Statement statement) { - String query = getQuery(statement); - - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - try { - ResultSet resultSet = session.execute(statement); - tracer().onResponse(span, resultSet.getExecutionInfo()); - return resultSet; - } catch (RuntimeException e) { - tracer().endExceptionally(span, e); - throw e; - } finally { - tracer().end(span); - } - } - } - - @Override - @NonNull - public CompletionStage executeAsync(@NonNull Statement statement) { - String query = getQuery(statement); - - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - CompletionStage stage = session.executeAsync(statement); - return stage.whenComplete( - (asyncResultSet, throwable) -> { - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().onResponse(span, asyncResultSet.getExecutionInfo()); - tracer().end(span); - } - }); - } - } - - @Override - @NonNull - public CompletionStage executeAsync(@NonNull String query) { - Span span = tracer().startSpan(session, query); - try (Scope ignored = tracer().startScope(span)) { - CompletionStage stage = session.executeAsync(query); - return stage.whenComplete( - (asyncResultSet, throwable) -> { - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().onResponse(span, asyncResultSet.getExecutionInfo()); - tracer().end(span); - } - }); - } - } - - private static String getQuery(Statement statement) { - String query = null; - if (statement instanceof SimpleStatement) { - query = ((SimpleStatement) statement).getQuery(); - } else if (statement instanceof BoundStatement) { - query = ((BoundStatement) statement).getPreparedStatement().getQuery(); - } - - return query == null ? "" : query; - } -} diff --git a/instrumentation/cassandra/cassandra-4.0/src/test/groovy/CassandraClientTest.groovy b/instrumentation/cassandra/cassandra-4.0/src/test/groovy/CassandraClientTest.groovy deleted file mode 100644 index c974c238e3..0000000000 --- a/instrumentation/cassandra/cassandra-4.0/src/test/groovy/CassandraClientTest.groovy +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.datastax.oss.driver.api.core.CqlSession -import com.datastax.oss.driver.api.core.config.DefaultDriverOption -import com.datastax.oss.driver.api.core.config.DriverConfigLoader -import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.sdk.trace.data.SpanData -import java.time.Duration -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.testcontainers.containers.GenericContainer -import org.testcontainers.containers.output.Slf4jLogConsumer -import spock.lang.Shared - -class CassandraClientTest extends AgentTestRunner { - private static final Logger log = LoggerFactory.getLogger(CassandraClientTest) - - @Shared - GenericContainer cassandra - @Shared - int cassandraPort - - def setupSpec() { - cassandra = new GenericContainer("cassandra:4.0") - .withExposedPorts(9042) - .withLogConsumer(new Slf4jLogConsumer(log)) - .withStartupTimeout(Duration.ofSeconds(120)) - cassandra.start() - - cassandraPort = cassandra.getMappedPort(9042) - } - - def cleanupSpec() { - cassandra.stop() - } - - def "test sync"() { - setup: - CqlSession session = getSession(keyspace) - - session.execute(statement) - - expect: - assertTraces(1) { - trace(0, 1) { - cassandraSpan(it, 0, expectedStatement, keyspace) - } - } - - cleanup: - session.close() - - where: - keyspace | statement | expectedStatement - null | "DROP KEYSPACE IF EXISTS sync_test" | "DROP KEYSPACE IF EXISTS sync_test" - null | "CREATE KEYSPACE sync_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}" | "CREATE KEYSPACE sync_test WITH REPLICATION = {?:?, ?:?}" - "sync_test" | "CREATE TABLE sync_test.users ( id UUID PRIMARY KEY, name text )" | "CREATE TABLE sync_test.users ( id UUID PRIMARY KEY, name text )" - "sync_test" | "INSERT INTO sync_test.users (id, name) values (uuid(), 'alice')" | "INSERT INTO sync_test.users (id, name) values (uuid(), ?)" - "sync_test" | "SELECT * FROM users where name = 'alice' ALLOW FILTERING" | "SELECT * FROM users where name = ? ALLOW FILTERING" - } - - def "test async"() { - setup: - CqlSession session = getSession(keyspace) - - runUnderTrace("parent") { - session.executeAsync(statement).toCompletableFuture().get() - } - - expect: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - cassandraSpan(it, 1, expectedStatement, keyspace, span(0)) - } - } - - cleanup: - session.close() - - where: - keyspace | statement | expectedStatement - null | "DROP KEYSPACE IF EXISTS async_test" | "DROP KEYSPACE IF EXISTS async_test" - null | "CREATE KEYSPACE async_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}" | "CREATE KEYSPACE async_test WITH REPLICATION = {?:?, ?:?}" - "async_test" | "CREATE TABLE async_test.users ( id UUID PRIMARY KEY, name text )" | "CREATE TABLE async_test.users ( id UUID PRIMARY KEY, name text )" - "async_test" | "INSERT INTO async_test.users (id, name) values (uuid(), 'alice')" | "INSERT INTO async_test.users (id, name) values (uuid(), ?)" - "async_test" | "SELECT * FROM users where name = 'alice' ALLOW FILTERING" | "SELECT * FROM users where name = ? ALLOW FILTERING" - } - - def cassandraSpan(TraceAssert trace, int index, String statement, String keyspace, Object parentSpan = null, Throwable exception = null) { - trace.span(index) { - name statement - kind CLIENT - if (parentSpan == null) { - hasNoParent() - } else { - childOf((SpanData) parentSpan) - } - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_PORT.key" cassandraPort - "$SemanticAttributes.DB_SYSTEM.key" "cassandra" - "$SemanticAttributes.DB_NAME.key" keyspace - "$SemanticAttributes.DB_STATEMENT.key" statement - } - } - } - - def getSession(String keyspace) { - DriverConfigLoader configLoader = DefaultDriverConfigLoader.builder() - .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(0)) - .build() - return CqlSession.builder() - .addContactPoint(new InetSocketAddress("localhost", cassandraPort)) - .withConfigLoader(configLoader) - .withLocalDatacenter("datacenter1") - .withKeyspace((String) keyspace) - .build() - } -} diff --git a/instrumentation/classloaders/classloaders.gradle b/instrumentation/classloaders/classloaders.gradle deleted file mode 100644 index 41a638a14a..0000000000 --- a/instrumentation/classloaders/classloaders.gradle +++ /dev/null @@ -1,7 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - compileOnly project(':javaagent-bootstrap') - - testImplementation project(':javaagent-bootstrap') -} \ No newline at end of file diff --git a/instrumentation/classloaders/jboss-testing/jboss-testing.gradle b/instrumentation/classloaders/jboss-testing/jboss-testing.gradle deleted file mode 100644 index b5e79a300f..0000000000 --- a/instrumentation/classloaders/jboss-testing/jboss-testing.gradle +++ /dev/null @@ -1,8 +0,0 @@ -ext.skipPublish = true -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - testImplementation project(':instrumentation:classloaders') - - testImplementation group: 'org.jboss.modules', name: 'jboss-modules', version: '1.3.10.Final' -} diff --git a/instrumentation/classloaders/jboss-testing/src/test/groovy/JBossClassloadingTest.groovy b/instrumentation/classloaders/jboss-testing/src/test/groovy/JBossClassloadingTest.groovy deleted file mode 100644 index 94e7739465..0000000000 --- a/instrumentation/classloaders/jboss-testing/src/test/groovy/JBossClassloadingTest.groovy +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.jboss.modules.ModuleFinder -import org.jboss.modules.ModuleIdentifier -import org.jboss.modules.ModuleLoadException -import org.jboss.modules.ModuleLoader -import org.jboss.modules.ModuleSpec - -class JBossClassloadingTest extends AgentTestRunner { - def "delegates to bootstrap class loader for agent classes"() { - setup: - def moduleFinders = new ModuleFinder[1] - moduleFinders[0] = new ModuleFinder() { - @Override - ModuleSpec findModule(ModuleIdentifier identifier, ModuleLoader delegateLoader) throws ModuleLoadException { - return ModuleSpec.build(identifier).create() - } - } - def moduleLoader = new ModuleLoader(moduleFinders) - def moduleId = ModuleIdentifier.fromString("test") - def testModule = moduleLoader.loadModule(moduleId) - def classLoader = testModule.getClassLoader() - - when: - Class clazz - try { - clazz = Class.forName("io.opentelemetry.javaagent.instrumentation.api.concurrent.State", false, classLoader) - } catch (ClassNotFoundException e) { - } - - then: - assert clazz != null - assert clazz.getClassLoader() == null - } -} diff --git a/instrumentation/classloaders/osgi-testing/osgi-testing.gradle b/instrumentation/classloaders/osgi-testing/osgi-testing.gradle deleted file mode 100644 index 3259b05efa..0000000000 --- a/instrumentation/classloaders/osgi-testing/osgi-testing.gradle +++ /dev/null @@ -1,13 +0,0 @@ -ext.skipPublish = true -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - testImplementation project(':instrumentation:classloaders') - - // TODO: we should separate core and Eclipse tests at some point, - // but right now core-specific tests are quite dump and are run with - // core version provided by Eclipse implementation. - //testImplementation group: 'org.osgi', name: 'org.osgi.core', version: '4.0.0' - testImplementation group: 'org.eclipse.platform', name: 'org.eclipse.osgi', version: '3.13.200' - testImplementation group: 'org.apache.felix', name: 'org.apache.felix.framework', version: '6.0.2' -} diff --git a/instrumentation/classloaders/osgi-testing/src/test/groovy/OSGIClassloadingTest.groovy b/instrumentation/classloaders/osgi-testing/src/test/groovy/OSGIClassloadingTest.groovy deleted file mode 100644 index 62cbd7f24e..0000000000 --- a/instrumentation/classloaders/osgi-testing/src/test/groovy/OSGIClassloadingTest.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.felix.framework.BundleWiringImpl -import org.eclipse.osgi.internal.debug.Debug -import org.eclipse.osgi.internal.framework.EquinoxConfiguration -import org.eclipse.osgi.internal.loader.BundleLoader -import org.eclipse.osgi.internal.loader.ModuleClassLoader -import org.eclipse.osgi.internal.loader.classpath.ClasspathManager -import org.eclipse.osgi.storage.BundleInfo - -class OSGIClassloadingTest extends AgentTestRunner { - def "OSGI delegates to bootstrap class loader for agent classes"() { - when: - def clazz - if (args == 1) { - clazz = loader.loadClass("io.opentelemetry.javaagent.instrumentation.api.concurrent.State") - } else { - clazz = loader.loadClass("io.opentelemetry.javaagent.instrumentation.api.concurrent.State", false) - } - - then: - assert clazz != null - assert clazz.getClassLoader() == null - - where: - loader | args - new TestClassLoader() | 1 - new TestClassLoader() | 2 - new BundleWiringImpl.BundleClassLoader(null, null, null) | 1 - new BundleWiringImpl.BundleClassLoader(null, null, null) | 2 - } - - static class TestClassLoader extends ModuleClassLoader { - - TestClassLoader() { - super(null) - } - - @Override - protected BundleInfo.Generation getGeneration() { - return null - } - - @Override - protected Debug getDebug() { - return null - } - - @Override - ClasspathManager getClasspathManager() { - return null - } - - @Override - protected EquinoxConfiguration getConfiguration() { - return null - } - - @Override - BundleLoader getBundleLoader() { - return null - } - - @Override - boolean isRegisteredAsParallel() { - return false - } - } -} diff --git a/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ClassLoaderInstrumentation.java b/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ClassLoaderInstrumentation.java deleted file mode 100644 index a50dae0108..0000000000 --- a/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ClassLoaderInstrumentation.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaclassloader; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedNoneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isProtected; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.tooling.Constants; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/* - * Some class loaders do not delegate to their parent, so classes in those class loaders - * will not be able to see classes in the bootstrap class loader. - * - * In particular, instrumentation on classes in those class loaders will not be able to see - * the shaded OpenTelemetry API classes in the bootstrap class loader. - * - * This instrumentation forces all class loaders to delegate to the bootstrap class loader - * for the classes that we have put in the bootstrap class loader. - */ -public class ClassLoaderInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - // just an optimization to exclude common class loaders that are known to delegate to the - // bootstrap loader (or happen to _be_ the bootstrap loader) - return namedNoneOf( - "java.lang.ClassLoader", - "com.ibm.oti.vm.BootstrapClassLoader", - "io.opentelemetry.javaagent.instrumentation.api.AgentClassLoader") - .and(extendsClass(named("java.lang.ClassLoader"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("loadClass")) - .and( - takesArguments(1) - .and(takesArgument(0, named("java.lang.String"))) - .or( - takesArguments(2) - .and(takesArgument(0, named("java.lang.String"))) - .and(takesArgument(1, named("boolean"))))) - .and(isPublic().or(isProtected())) - .and(not(isStatic())), - ClassLoaderInstrumentation.class.getName() + "$LoadClassAdvice"); - } - - public static class LoadClassAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - public static Class onEnter(@Advice.Argument(0) String name) { - // need to use call depth here to prevent re-entry from call to Class.forName() below - // because on some JVMs (e.g. IBM's, though IBM bootstrap loader is explicitly excluded above) - // Class.forName() ends up calling loadClass() on the bootstrap loader which would then come - // back to this instrumentation over and over, causing a StackOverflowError - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(ClassLoader.class); - if (callDepth > 0) { - return null; - } - - try { - // TODO (trask) need to load BootstrapPackagePrefixesHolder itself from the bootstrap class - // loader, but at the same time need to be careful about re-entry due to comment above, - // so for now using the old constant, which works because Constants is injected into the - // class loader - // for (String prefix : BootstrapPackagePrefixesHolder.getBoostrapPackagePrefixes()) { - for (String prefix : Constants.BOOTSTRAP_PACKAGE_PREFIXES) { - if (name.startsWith(prefix)) { - try { - return Class.forName(name, false, null); - } catch (ClassNotFoundException ignored) { - } - } - } - } finally { - // need to reset it right away, not waiting until onExit() - // otherwise it will prevent this instrumentation from being applied when loadClass() - // ends up calling a ClassFileTransformer which ends up calling loadClass() further down the - // stack on one of our bootstrap packages (since the call depth check would then suppress - // the nested loadClass instrumentation) - CallDepthThreadLocalMap.reset(ClassLoader.class); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class) - public static void onExit( - @Advice.Return(readOnly = false) Class result, - @Advice.Enter Class resultFromBootstrapLoader) { - if (resultFromBootstrapLoader != null) { - result = resultFromBootstrapLoader; - } - } - } -} diff --git a/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ClassLoaderInstrumentationModule.java b/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ClassLoaderInstrumentationModule.java deleted file mode 100644 index 4e6accdcb2..0000000000 --- a/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ClassLoaderInstrumentationModule.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaclassloader; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class ClassLoaderInstrumentationModule extends InstrumentationModule { - public ClassLoaderInstrumentationModule() { - super("classloader"); - } - - @Override - protected String[] additionalHelperClassNames() { - return new String[] {"io.opentelemetry.javaagent.tooling.Constants"}; - } - - @Override - public List typeInstrumentations() { - return asList(new ClassLoaderInstrumentation(), new ResourceInjectionInstrumentation()); - } -} diff --git a/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ResourceInjectionInstrumentation.java b/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ResourceInjectionInstrumentation.java deleted file mode 100644 index 34ed6c2044..0000000000 --- a/instrumentation/classloaders/src/main/java/io/opentelemetry/javaagent/instrumentation/javaclassloader/ResourceInjectionInstrumentation.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaclassloader; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.bootstrap.HelperResources; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * Instruments {@link ClassLoader} to have calls to get resources intercepted and check our map of - * helper resources that is filled by instrumentation when they need helpers. - * - *

We currently only intercept {@link ClassLoader#getResources(String)} because this is the case - * we are currently always interested in, where it's used for service loading. - */ -public class ResourceInjectionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("java.lang.ClassLoader")); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isMethod().and(named("getResources")).and(takesArguments(String.class)), - ResourceInjectionInstrumentation.class.getName() + "$GetResourcesAdvice"); - } - - public static class GetResourcesAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit( - @Advice.This ClassLoader classLoader, - @Advice.Argument(0) String name, - @Advice.Return(readOnly = false) Enumeration resources) { - URL helper = HelperResources.load(classLoader, name); - if (helper == null) { - return; - } - - if (!resources.hasMoreElements()) { - resources = Collections.enumeration(Collections.singleton(helper)); - return; - } - - List result = Collections.list(resources); - boolean duplicate = false; - for (URL loadedUrl : result) { - if (helper.sameFile(loadedUrl)) { - duplicate = true; - break; - } - } - if (!duplicate) { - result.add(helper); - } - - resources = Collections.enumeration(result); - } - } -} diff --git a/instrumentation/classloaders/src/test/groovy/ClassLoadingTest.groovy b/instrumentation/classloaders/src/test/groovy/ClassLoadingTest.groovy deleted file mode 100644 index e5aa671cf4..0000000000 --- a/instrumentation/classloaders/src/test/groovy/ClassLoadingTest.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner - -class ClassLoadingTest extends AgentTestRunner { - def "delegates to bootstrap class loader for agent classes"() { - setup: - def classLoader = new NonDelegatingURLClassLoader() - - when: - Class clazz - try { - clazz = Class.forName("io.opentelemetry.javaagent.instrumentation.api.concurrent.State", false, classLoader) - } catch (ClassNotFoundException e) { - } - - then: - assert clazz != null - assert clazz.getClassLoader() == null - } - - static class NonDelegatingURLClassLoader extends URLClassLoader { - - NonDelegatingURLClassLoader() { - super(new URL[0]) - } - - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - synchronized (getClassLoadingLock(name)) { - Class clazz = findLoadedClass(name) - if (clazz == null) { - clazz = findClass(name) - } - if (resolve) { - resolveClass(clazz) - } - return clazz - } - } - } -} diff --git a/instrumentation/classloaders/src/test/groovy/ResourceInjectionTest.groovy b/instrumentation/classloaders/src/test/groovy/ResourceInjectionTest.groovy deleted file mode 100644 index ab0b324b9b..0000000000 --- a/instrumentation/classloaders/src/test/groovy/ResourceInjectionTest.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.util.gc.GcUtils.awaitGc - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.javaagent.tooling.HelperInjector -import java.lang.ref.WeakReference -import java.util.concurrent.atomic.AtomicReference - -class ResourceInjectionTest extends AgentTestRunner { - - def "resources injected to non-delegating classloader"() { - setup: - String resourceName = 'test-resources/test-resource.txt' - HelperInjector injector = new HelperInjector("test", [], [resourceName]) - AtomicReference emptyLoader = new AtomicReference<>(new URLClassLoader(new URL[0], (ClassLoader) null)) - - when: - def resourceUrls = emptyLoader.get().getResources(resourceName) - then: - !resourceUrls.hasMoreElements() - - when: - URLClassLoader notInjectedLoader = new URLClassLoader(new URL[0], (ClassLoader) null) - - injector.transform(null, null, emptyLoader.get(), null) - resourceUrls = emptyLoader.get().getResources(resourceName) - - then: - resourceUrls.hasMoreElements() - resourceUrls.nextElement().openStream().text.trim() == 'Hello world!' - - !notInjectedLoader.getResources(resourceName).hasMoreElements() - - when: "references to emptyLoader are gone" - emptyLoader.get().close() // cleanup - def ref = new WeakReference(emptyLoader.get()) - emptyLoader.set(null) - - awaitGc(ref) - - then: "HelperInjector doesn't prevent it from being collected" - null == ref.get() - } -} diff --git a/instrumentation/classloaders/src/test/resources/test-resources/test-resource.txt b/instrumentation/classloaders/src/test/resources/test-resources/test-resource.txt deleted file mode 100644 index cd0875583a..0000000000 --- a/instrumentation/classloaders/src/test/resources/test-resources/test-resource.txt +++ /dev/null @@ -1 +0,0 @@ -Hello world! diff --git a/instrumentation/classloaders/tomcat-testing/src/test/groovy/TomcatClassloadingTest.groovy b/instrumentation/classloaders/tomcat-testing/src/test/groovy/TomcatClassloadingTest.groovy deleted file mode 100644 index d460487a4f..0000000000 --- a/instrumentation/classloaders/tomcat-testing/src/test/groovy/TomcatClassloadingTest.groovy +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State -import org.apache.catalina.WebResource -import org.apache.catalina.WebResourceRoot -import org.apache.catalina.loader.ParallelWebappClassLoader - -class TomcatClassloadingTest extends AgentTestRunner { - - WebResourceRoot resources = Mock(WebResourceRoot) { - getResource(_) >> Mock(WebResource) - listResources(_) >> [] - // Looks like 9.x.x needs this one: - getResources(_) >> [] - } - ParallelWebappClassLoader classloader = new ParallelWebappClassLoader(null) - - def "tomcat class loading delegates to parent for agent classes"() { - setup: - classloader.setResources(resources) - classloader.init() - classloader.start() - - when: - // If instrumentation didn't work this would blow up with NPE due to incomplete resources mocking - def clazz = classloader.loadClass("io.opentelemetry.javaagent.instrumentation.api.concurrent.State") - - then: - clazz == State - } -} diff --git a/instrumentation/classloaders/tomcat-testing/tomcat-testing.gradle b/instrumentation/classloaders/tomcat-testing/tomcat-testing.gradle deleted file mode 100644 index d7f27b9e95..0000000000 --- a/instrumentation/classloaders/tomcat-testing/tomcat-testing.gradle +++ /dev/null @@ -1,20 +0,0 @@ -ext.skipPublish = true - -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.tomcat" - module = 'tomcat-catalina' - versions = "[3.0.14,)" - assertInverse = true - } -} - -dependencies { - testImplementation project(':instrumentation:classloaders') - - // This is the earliest version that has org.apache.catalina.loader.ParallelWebappClassLoader - // which is used in the test - testLibrary group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '8.0.14' -} diff --git a/instrumentation/couchbase/couchbase-2.0/couchbase-2.0.gradle b/instrumentation/couchbase/couchbase-2.0/couchbase-2.0.gradle deleted file mode 100644 index 6ca02ecd69..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/couchbase-2.0.gradle +++ /dev/null @@ -1,37 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - // Version 2.7.5 and 2.7.8 were not released properly and muzzle cannot test against it causing failure. - // So we have to skip them resulting in this verbose setup. - pass { - group = 'com.couchbase.client' - module = 'java-client' - versions = "[2.0.0,2.7.5)" - } - pass { - group = 'com.couchbase.client' - module = 'java-client' - versions = "[2.7.6,2.7.8)" - } - pass { - group = 'com.couchbase.client' - module = 'java-client' - versions = "[2.7.9,3.0.0)" - } - fail { - group = 'com.couchbase.client' - module = 'couchbase-client' - versions = "(,)" - } -} - -dependencies { - implementation project(':instrumentation:rxjava-1.0:library') - - library group: 'com.couchbase.client', name: 'java-client', version: '2.0.0' - - testImplementation project(':instrumentation:couchbase:couchbase-testing') - - latestDepTestLibrary group: 'org.springframework.data', name: 'spring-data-couchbase', version: '3.+' - latestDepTestLibrary group: 'com.couchbase.client', name: 'java-client', version: '2.+' -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseBucketInstrumentation.java b/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseBucketInstrumentation.java deleted file mode 100644 index fe6f247248..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseBucketInstrumentation.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; - -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import com.couchbase.client.java.CouchbaseCluster; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import rx.Observable; - -public class CouchbaseBucketInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return namedOneOf( - "com.couchbase.client.java.bucket.DefaultAsyncBucketManager", - "com.couchbase.client.java.CouchbaseAsyncBucket"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(isPublic()).and(returns(named("rx.Observable"))).and(not(named("query"))), - CouchbaseBucketInstrumentation.class.getName() + "$CouchbaseClientAdvice"); - transformers.put( - isMethod().and(isPublic()).and(returns(named("rx.Observable"))).and(named("query")), - CouchbaseBucketInstrumentation.class.getName() + "$CouchbaseClientQueryAdvice"); - return transformers; - } - - public static class CouchbaseClientAdvice { - - @Advice.OnMethodEnter - public static int trackCallDepth() { - return CallDepthThreadLocalMap.incrementCallDepth(CouchbaseCluster.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void subscribeResult( - @Advice.Enter int callDepth, - @Advice.Origin Method method, - @Advice.FieldValue("bucket") String bucket, - @Advice.Return(readOnly = false) Observable result) { - if (callDepth > 0) { - return; - } - CallDepthThreadLocalMap.reset(CouchbaseCluster.class); - result = Observable.create(CouchbaseOnSubscribe.create(result, bucket, method)); - } - } - - public static class CouchbaseClientQueryAdvice { - - @Advice.OnMethodEnter - public static int trackCallDepth() { - return CallDepthThreadLocalMap.incrementCallDepth(CouchbaseCluster.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class) - public static void subscribeResult( - @Advice.Enter int callDepth, - @Advice.Origin Method method, - @Advice.FieldValue("bucket") String bucket, - @Advice.Argument(value = 0, optional = true) Object query, - @Advice.Return(readOnly = false) Observable result) { - if (callDepth > 0) { - return; - } - CallDepthThreadLocalMap.reset(CouchbaseCluster.class); - - if (query != null) { - // A query can be of many different types. We could track the creation of them and try to - // rewind back to when they were created from a string, but for now we rely on toString() - // returning something useful. That seems to be the case. If we're starting to see strange - // query texts, this is the place to look! - result = Observable.create(CouchbaseOnSubscribe.create(result, bucket, query)); - } else { - result = Observable.create(CouchbaseOnSubscribe.create(result, bucket, method)); - } - } - } -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseClientTracer.java b/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseClientTracer.java deleted file mode 100644 index dd9f5f970b..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseClientTracer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; - -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; - -public class CouchbaseClientTracer extends DatabaseClientTracer { - private static final CouchbaseClientTracer TRACER = new CouchbaseClientTracer(); - - public static CouchbaseClientTracer tracer() { - return TRACER; - } - - @Override - protected String normalizeQuery(Method method) { - Class declaringClass = method.getDeclaringClass(); - String className = - declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", ""); - return className + "." + method.getName(); - } - - @Override - protected String dbSystem(Void connection) { - return DbSystem.COUCHBASE; - } - - @Override - protected InetSocketAddress peerAddress(Void connection) { - return null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.couchbase"; - } -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseClusterInstrumentation.java b/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseClusterInstrumentation.java deleted file mode 100644 index 44724506dd..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseClusterInstrumentation.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; - -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import com.couchbase.client.java.CouchbaseCluster; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import rx.Observable; - -public class CouchbaseClusterInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return namedOneOf( - "com.couchbase.client.java.cluster.DefaultAsyncClusterManager", - "com.couchbase.client.java.CouchbaseAsyncCluster"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(returns(named("rx.Observable"))).and(not(named("core"))), - CouchbaseClusterInstrumentation.class.getName() + "$CouchbaseClientAdvice"); - } - - public static class CouchbaseClientAdvice { - - @Advice.OnMethodEnter - public static int trackCallDepth() { - return CallDepthThreadLocalMap.incrementCallDepth(CouchbaseCluster.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void subscribeResult( - @Advice.Enter int callDepth, - @Advice.Origin Method method, - @Advice.Return(readOnly = false) Observable result) { - if (callDepth > 0) { - return; - } - CallDepthThreadLocalMap.reset(CouchbaseCluster.class); - - result = Observable.create(CouchbaseOnSubscribe.create(result, null, method)); - } - } -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseInstrumentationModule.java b/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseInstrumentationModule.java deleted file mode 100644 index bf2dfac790..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseInstrumentationModule.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class CouchbaseInstrumentationModule extends InstrumentationModule { - public CouchbaseInstrumentationModule() { - super("couchbase", "couchbase-2.0"); - } - - @Override - protected String[] additionalHelperClassNames() { - return new String[] { - "rx.__OpenTelemetryTracingUtil", - }; - } - - @Override - public List typeInstrumentations() { - return asList(new CouchbaseBucketInstrumentation(), new CouchbaseClusterInstrumentation()); - } -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseOnSubscribe.java b/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseOnSubscribe.java deleted file mode 100644 index 7e25441d7c..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseOnSubscribe.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT; -import static io.opentelemetry.javaagent.instrumentation.couchbase.v2_0.CouchbaseClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.rxjava.TracedOnSubscribe; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.lang.reflect.Method; -import rx.Observable; - -public class CouchbaseOnSubscribe extends TracedOnSubscribe { - private final String bucket; - private final String query; - - public static CouchbaseOnSubscribe create( - Observable originalObservable, String bucket, Method method) { - Class declaringClass = method.getDeclaringClass(); - String className = - declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", ""); - return new CouchbaseOnSubscribe<>( - originalObservable, bucket, className + "." + method.getName()); - } - - public static CouchbaseOnSubscribe create( - Observable originalObservable, String bucket, Object query) { - return new CouchbaseOnSubscribe<>( - originalObservable, bucket, CouchbaseQueryNormalizer.normalize(query)); - } - - private CouchbaseOnSubscribe(Observable originalObservable, String bucket, String query) { - super(originalObservable, query, tracer(), CLIENT); - - this.bucket = bucket; - this.query = query; - } - - @Override - protected void decorateSpan(Span span) { - span.setAttribute(SemanticAttributes.DB_SYSTEM, DbSystem.COUCHBASE); - span.setAttribute(SemanticAttributes.DB_NAME, bucket); - span.setAttribute(SemanticAttributes.DB_STATEMENT, query); - } -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizer.java b/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizer.java deleted file mode 100644 index 18f3b377ab..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizer.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled; - -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class CouchbaseQueryNormalizer { - private static final Logger log = LoggerFactory.getLogger(CouchbaseQueryNormalizer.class); - private static final boolean NORMALIZATION_ENABLED = - isQueryNormalizationEnabled("couchbase", "couchbase-2.0"); - - private static final Class QUERY_CLASS; - private static final Class STATEMENT_CLASS; - private static final Class N1QL_QUERY_CLASS; - private static final MethodHandle N1QL_GET_STATEMENT; - private static final Class ANALYTICS_QUERY_CLASS; - private static final MethodHandle ANALYTICS_GET_STATEMENT; - - static { - Class queryClass; - try { - queryClass = Class.forName("com.couchbase.client.java.query.Query"); - } catch (Exception e) { - queryClass = null; - } - QUERY_CLASS = queryClass; - - Class statementClass; - try { - statementClass = Class.forName("com.couchbase.client.java.query.Statement"); - } catch (Exception e) { - statementClass = null; - } - STATEMENT_CLASS = statementClass; - - Class n1qlQueryClass; - MethodHandle n1qlGetStatement; - try { - n1qlQueryClass = Class.forName("com.couchbase.client.java.query.N1qlQuery"); - n1qlGetStatement = - MethodHandles.publicLookup() - .findVirtual( - n1qlQueryClass, - "statement", - MethodType.methodType( - Class.forName("com.couchbase.client.java.query.Statement"))); - } catch (Exception e) { - n1qlQueryClass = null; - n1qlGetStatement = null; - } - N1QL_QUERY_CLASS = n1qlQueryClass; - N1QL_GET_STATEMENT = n1qlGetStatement; - - Class analyticsQueryClass; - MethodHandle analyticsGetStatement; - try { - analyticsQueryClass = Class.forName("com.couchbase.client.java.analytics.AnalyticsQuery"); - analyticsGetStatement = - MethodHandles.publicLookup() - .findVirtual(analyticsQueryClass, "statement", MethodType.methodType(String.class)); - } catch (Exception e) { - analyticsQueryClass = null; - analyticsGetStatement = null; - } - ANALYTICS_QUERY_CLASS = analyticsQueryClass; - ANALYTICS_GET_STATEMENT = analyticsGetStatement; - } - - public static String normalize(Object query) { - if (query instanceof String) { - return normalizeString((String) query); - } - // Query is present in Couchbase [2.0.0, 2.2.0) - // Statement is present starting from Couchbase 2.1.0 - if (QUERY_CLASS != null && QUERY_CLASS.isAssignableFrom(query.getClass()) - || STATEMENT_CLASS != null && STATEMENT_CLASS.isAssignableFrom(query.getClass())) { - return normalizeString(query.toString()); - } - // SpatialViewQuery is present starting from Couchbase 2.1.0 - String queryClassName = query.getClass().getName(); - if (queryClassName.equals("com.couchbase.client.java.view.ViewQuery") - || queryClassName.equals("com.couchbase.client.java.view.SpatialViewQuery")) { - return query.toString(); - } - // N1qlQuery is present starting from Couchbase 2.2.0 - if (N1QL_QUERY_CLASS != null && N1QL_QUERY_CLASS.isAssignableFrom(query.getClass())) { - String statement = getStatementString(N1QL_GET_STATEMENT, query); - if (statement != null) { - return normalizeString(statement); - } - } - // AnalyticsQuery is present starting from Couchbase 2.4.3 - if (ANALYTICS_QUERY_CLASS != null && ANALYTICS_QUERY_CLASS.isAssignableFrom(query.getClass())) { - String statement = getStatementString(ANALYTICS_GET_STATEMENT, query); - if (statement != null) { - return normalizeString(statement); - } - } - return query.getClass().getSimpleName(); - } - - private static String getStatementString(MethodHandle handle, Object query) { - if (handle == null) { - return null; - } - try { - return handle.invoke(query).toString(); - } catch (Throwable throwable) { - return null; - } - } - - private static String normalizeString(String query) { - if (!NORMALIZATION_ENABLED || query == null) { - return query; - } - try { - return SqlNormalizer.normalize(query); - } catch (ParseException e) { - log.debug("Could not normalize Couchbase query", e); - return null; - } - } - - private CouchbaseQueryNormalizer() {} -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/CouchbaseAsyncClientTest.groovy b/instrumentation/couchbase/couchbase-2.0/src/test/groovy/CouchbaseAsyncClientTest.groovy deleted file mode 100644 index 43b302320f..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/CouchbaseAsyncClientTest.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class CouchbaseAsyncClientTest extends AbstractCouchbaseAsyncClientTest { -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/CouchbaseClientTest.groovy b/instrumentation/couchbase/couchbase-2.0/src/test/groovy/CouchbaseClientTest.groovy deleted file mode 100644 index aed568b0b0..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/CouchbaseClientTest.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class CouchbaseClientTest extends AbstractCouchbaseClientTest { -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizerTest.groovy b/instrumentation/couchbase/couchbase-2.0/src/test/groovy/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizerTest.groovy deleted file mode 100644 index 1720f4d45e..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQueryNormalizerTest.groovy +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0 - -import com.couchbase.client.java.analytics.AnalyticsQuery -import com.couchbase.client.java.query.N1qlQuery -import com.couchbase.client.java.query.Select -import com.couchbase.client.java.query.dsl.Expression -import com.couchbase.client.java.view.SpatialViewQuery -import com.couchbase.client.java.view.ViewQuery -import spock.lang.Specification -import spock.lang.Unroll - -class CouchbaseQueryNormalizerTest extends Specification { - @Unroll - def "should normalize #desc query"() { - when: - def normalized = CouchbaseQueryNormalizer.normalize(query) - - then: - // the analytics query ends up with trailing ';' in earlier couchbase version, but no trailing ';' in later couchbase version - normalized.replaceFirst(';$', '') == expected - - where: - desc | query | expected - "plain string" | "SELECT field1 FROM `test` WHERE field2 = 'asdf'" | "SELECT field1 FROM `test` WHERE field2 = ?" - "Statement" | Select.select("field1").from("test").where(Expression.path("field2").eq(Expression.s("asdf"))) | "SELECT field1 FROM test WHERE field2 = ?" - "N1QL" | N1qlQuery.simple("SELECT field1 FROM `test` WHERE field2 = 'asdf'") | "SELECT field1 FROM `test` WHERE field2 = ?" - "Analytics" | AnalyticsQuery.simple("SELECT field1 FROM `test` WHERE field2 = 'asdf'") | "SELECT field1 FROM `test` WHERE field2 = ?" - "View" | ViewQuery.from("design", "view").skip(10) | 'ViewQuery(design/view){params="skip=10"}' - "SpatialView" | SpatialViewQuery.from("design", "view").skip(10) | 'skip=10' - } -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringRepositoryTest.groovy b/instrumentation/couchbase/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringRepositoryTest.groovy deleted file mode 100644 index b59b287da5..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringRepositoryTest.groovy +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -class CouchbaseSpringRepositoryTest extends AbstractCouchbaseSpringRepositoryTest { -} diff --git a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringTemplateTest.groovy b/instrumentation/couchbase/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringTemplateTest.groovy deleted file mode 100644 index 3f355463f0..0000000000 --- a/instrumentation/couchbase/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringTemplateTest.groovy +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -class CouchbaseSpringTemplateTest extends AbstractCouchbaseSpringTemplateTest { -} diff --git a/instrumentation/couchbase/couchbase-2.6/couchbase-2.6.gradle b/instrumentation/couchbase/couchbase-2.6/couchbase-2.6.gradle deleted file mode 100644 index 575e5a12f6..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/couchbase-2.6.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = 'com.couchbase.client' - module = 'java-client' - versions = "[2.6.0,3)" - // Version 2.7.5 and 2.7.8 were not released properly and muzzle cannot test against it causing failure. - skipVersions += ['2.7.5', '2.7.8'] - assertInverse = true - } - fail { - group = 'com.couchbase.client' - module = 'couchbase-client' - versions = "(,)" - } -} - -dependencies { - implementation project(':instrumentation:rxjava-1.0:library') - - library group: 'com.couchbase.client', name: 'java-client', version: '2.6.0' - - testImplementation project(':instrumentation:couchbase:couchbase-2.0') - testImplementation project(':instrumentation:couchbase:couchbase-testing') - - testLibrary group: 'org.springframework.data', name: 'spring-data-couchbase', version: '3.1.0.RELEASE' - testLibrary group: 'com.couchbase.client', name: 'encryption', version: '1.0.0' - - latestDepTestLibrary group: 'org.springframework.data', name: 'spring-data-couchbase', version: '3.1+' - latestDepTestLibrary group: 'com.couchbase.client', name: 'java-client', version: '2.+' -} diff --git a/instrumentation/couchbase/couchbase-2.6/javaagent/src/test/groovy/CouchbaseSpanUtil.groovy b/instrumentation/couchbase/couchbase-2.6/javaagent/src/test/groovy/CouchbaseSpanUtil.groovy index eb04fe0f2d..477793bbcd 100644 --- a/instrumentation/couchbase/couchbase-2.6/javaagent/src/test/groovy/CouchbaseSpanUtil.groovy +++ b/instrumentation/couchbase/couchbase-2.6/javaagent/src/test/groovy/CouchbaseSpanUtil.groovy @@ -5,9 +5,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.sdk.trace.data.SpanData -import io.opentelemetry.api.trace.attributes.SemanticAttributes class CouchbaseSpanUtil { // Reusable span assertion method. Cannot directly override AbstractCouchbaseTest.assertCouchbaseSpan because diff --git a/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseCoreInstrumentation.java b/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseCoreInstrumentation.java deleted file mode 100644 index a396e3c23c..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseCoreInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_6; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.couchbase.client.core.message.CouchbaseRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class CouchbaseCoreInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.couchbase.client.core.CouchbaseCore"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(takesArgument(0, named("com.couchbase.client.core.message.CouchbaseRequest"))) - .and(named("send")), - CouchbaseCoreInstrumentation.class.getName() + "$CouchbaseCoreAdvice"); - } - - public static class CouchbaseCoreAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void addOperationIdToSpan(@Advice.Argument(0) CouchbaseRequest request) { - - Span parentSpan = Java8BytecodeBridge.currentSpan(); - if (parentSpan != null) { - // The scope from the initial rxJava subscribe is not available to the networking layer - // To transfer the span, the span is added to the context store - - ContextStore contextStore = - InstrumentationContext.get(CouchbaseRequest.class, Span.class); - - Span span = contextStore.get(request); - - if (span == null) { - span = parentSpan; - contextStore.put(request, span); - - span.setAttribute("couchbase.operation_id", request.operationId()); - } - } - } - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java b/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java deleted file mode 100644 index ac3cafed67..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_6; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class CouchbaseInstrumentationModule extends InstrumentationModule { - public CouchbaseInstrumentationModule() { - super("couchbase", "couchbase-2.6"); - } - - @Override - public List typeInstrumentations() { - return asList(new CouchbaseCoreInstrumentation(), new CouchbaseNetworkInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap("com.couchbase.client.core.message.CouchbaseRequest", Span.class.getName()); - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseNetworkInstrumentation.java b/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseNetworkInstrumentation.java deleted file mode 100644 index 970f93f029..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseNetworkInstrumentation.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.couchbase.v2_6; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.couchbase.client.core.message.CouchbaseRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class CouchbaseNetworkInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.couchbase.client.core.endpoint.AbstractGenericHandler"); - } - - @Override - public ElementMatcher typeMatcher() { - // Exact class because private fields are used - return nameStartsWith("com.couchbase.client.") - .and( - extendsClass(named("com.couchbase.client.core.endpoint.AbstractGenericHandler"))); - } - - @Override - public Map, String> transformers() { - // encode(ChannelHandlerContext ctx, REQUEST msg, List out) - return singletonMap( - isMethod() - .and(named("encode")) - .and(takesArguments(3)) - .and( - takesArgument( - 0, named("com.couchbase.client.deps.io.netty.channel.ChannelHandlerContext"))) - .and(takesArgument(2, named("java.util.List"))), - CouchbaseNetworkInstrumentation.class.getName() + "$CouchbaseNetworkAdvice"); - } - - public static class CouchbaseNetworkAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void addNetworkTagsToSpan( - @Advice.FieldValue("remoteHostname") String remoteHostname, - @Advice.FieldValue("remoteSocket") String remoteSocket, - @Advice.FieldValue("localSocket") String localSocket, - @Advice.Argument(1) CouchbaseRequest request) { - ContextStore contextStore = - InstrumentationContext.get(CouchbaseRequest.class, Span.class); - - Span span = contextStore.get(request); - if (span != null) { - NetPeerUtils.setNetPeer(span, remoteHostname, null); - - if (remoteSocket != null) { - int splitIndex = remoteSocket.lastIndexOf(":"); - if (splitIndex != -1) { - span.setAttribute( - SemanticAttributes.NET_PEER_PORT, - (long) Integer.parseInt(remoteSocket.substring(splitIndex + 1))); - } - } - - span.setAttribute("local.address", localSocket); - } - } - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseAsyncClient26Test.groovy b/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseAsyncClient26Test.groovy deleted file mode 100644 index f8e7b89158..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseAsyncClient26Test.groovy +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert - -class CouchbaseAsyncClient26Test extends AbstractCouchbaseAsyncClientTest { - - @Override - void assertCouchbaseCall(TraceAssert trace, int index, Object name, String bucketName = null, Object parentSpan = null) { - CouchbaseSpanUtil.assertCouchbaseCall(trace, index, name, bucketName, parentSpan) - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseClient26Test.groovy b/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseClient26Test.groovy deleted file mode 100644 index c9e86e1a96..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseClient26Test.groovy +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert - -class CouchbaseClient26Test extends AbstractCouchbaseClientTest { - @Override - void assertCouchbaseCall(TraceAssert trace, int index, Object name, String bucketName = null, Object parentSpan = null) { - CouchbaseSpanUtil.assertCouchbaseCall(trace, index, name, bucketName, parentSpan) - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseSpanUtil.groovy b/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseSpanUtil.groovy deleted file mode 100644 index 477793bbcd..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/CouchbaseSpanUtil.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.sdk.trace.data.SpanData - -class CouchbaseSpanUtil { - // Reusable span assertion method. Cannot directly override AbstractCouchbaseTest.assertCouchbaseSpan because - // Of the class hierarchy of these tests - static void assertCouchbaseCall(TraceAssert trace, int index, Object spanName, String bucketName = null, Object parentSpan = null) { - trace.span(index) { - name spanName - kind CLIENT - errored false - if (parentSpan == null) { - hasNoParent() - } else { - childOf((SpanData) parentSpan) - } - attributes { - - // Because of caching, not all requests hit the server so these attributes may be absent - "${SemanticAttributes.NET_PEER_NAME.key()}" { it == "localhost" || it == "127.0.0.1" || it == null } - "${SemanticAttributes.NET_PEER_PORT.key()}" { it == null || Number } - - "${SemanticAttributes.DB_SYSTEM.key()}" "couchbase" - if (bucketName != null) { - "${SemanticAttributes.DB_NAME.key()}" bucketName - } - - // Because of caching, not all requests hit the server so this tag may be absent - "local.address" { it == null || String } - - // Not all couchbase operations have operation id. Notably, 'ViewQuery's do not - // We assign a spanName of 'Bucket.query' and this is shared with n1ql queries - // that do have operation ids - "couchbase.operation_id" { it == null || String } - - "${SemanticAttributes.DB_STATEMENT.key()}" spanName - } - } - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/springdata/CouchbaseSpringRepository26Test.groovy b/instrumentation/couchbase/couchbase-2.6/src/test/groovy/springdata/CouchbaseSpringRepository26Test.groovy deleted file mode 100644 index 3807862877..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/springdata/CouchbaseSpringRepository26Test.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert - -class CouchbaseSpringRepository26Test extends AbstractCouchbaseSpringRepositoryTest { - - @Override - void assertCouchbaseCall(TraceAssert trace, int index, Object name, String bucketName = null, Object parentSpan = null) { - CouchbaseSpanUtil.assertCouchbaseCall(trace, index, name, bucketName, parentSpan) - } -} diff --git a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/springdata/CouchbaseSpringTemplate26Test.groovy b/instrumentation/couchbase/couchbase-2.6/src/test/groovy/springdata/CouchbaseSpringTemplate26Test.groovy deleted file mode 100644 index 409aad36a9..0000000000 --- a/instrumentation/couchbase/couchbase-2.6/src/test/groovy/springdata/CouchbaseSpringTemplate26Test.groovy +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert - -class CouchbaseSpringTemplate26Test extends AbstractCouchbaseSpringTemplateTest { - @Override - void assertCouchbaseCall(TraceAssert trace, int index, Object name, String bucketName = null, Object parentSpan = null) { - CouchbaseSpanUtil.assertCouchbaseCall(trace, index, name, bucketName, parentSpan) - } -} diff --git a/instrumentation/dropwizard-testing/dropwizard-testing.gradle b/instrumentation/dropwizard-testing/dropwizard-testing.gradle index 1d0d570d1e..d551a54cec 100644 --- a/instrumentation/dropwizard-testing/dropwizard-testing.gradle +++ b/instrumentation/dropwizard-testing/dropwizard-testing.gradle @@ -4,7 +4,7 @@ ext { apply from: "$rootDir/gradle/instrumentation.gradle" dependencies { - testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0') + testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0:javaagent') testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') // First version with DropwizardTestSupport: diff --git a/instrumentation/dropwizard-views-0.7/dropwizard-views-0.7.gradle b/instrumentation/dropwizard-views-0.7/dropwizard-views-0.7.gradle deleted file mode 100644 index 51eac72cde..0000000000 --- a/instrumentation/dropwizard-views-0.7/dropwizard-views-0.7.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = 'io.dropwizard' - module = 'dropwizard-views' - versions = "(,)" - } -} - -dependencies { - compileOnly group: 'io.dropwizard', name: 'dropwizard-views', version: '0.7.0' - - testImplementation group: 'io.dropwizard', name: 'dropwizard-views-freemarker', version: '0.7.0' - testImplementation group: 'io.dropwizard', name: 'dropwizard-views-mustache', version: '0.7.0' -} diff --git a/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardTracer.java b/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardTracer.java deleted file mode 100644 index 39a0369aef..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardTracer.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.dropwizardviews; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; - -public class DropwizardTracer extends BaseTracer { - private static final DropwizardTracer TRACER = new DropwizardTracer(); - - public static DropwizardTracer tracer() { - return TRACER; - } - - public Span startSpan(String spanName) { - return super.startSpan(spanName, Span.Kind.INTERNAL); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.dropwizard-views"; - } -} diff --git a/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewsInstrumentationModule.java b/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewsInstrumentationModule.java deleted file mode 100644 index dc1fe69501..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardViewsInstrumentationModule.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.dropwizardviews; - -import static io.opentelemetry.javaagent.instrumentation.dropwizardviews.DropwizardTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.dropwizard.views.View; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class DropwizardViewsInstrumentationModule extends InstrumentationModule { - public DropwizardViewsInstrumentationModule() { - super("dropwizard-views"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ViewRendererInstrumentation()); - } - - public static class ViewRendererInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("io.dropwizard.views.ViewRenderer"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("io.dropwizard.views.ViewRenderer")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("render")) - .and(takesArgument(0, named("io.dropwizard.views.View"))) - .and(isPublic()), - DropwizardViewsInstrumentationModule.class.getName() + "$RenderAdvice"); - } - } - - public static class RenderAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope onEnter(@Advice.Argument(0) View view) { - if (!Java8BytecodeBridge.currentSpan().getSpanContext().isValid()) { - return null; - } - Span span = tracer().startSpan("Render " + view.getTemplateName()); - return new SpanWithScope(span, span.makeCurrent()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - if (spanWithScope == null) { - return; - } - Span span = spanWithScope.getSpan(); - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - spanWithScope.closeScope(); - } - } -} diff --git a/instrumentation/dropwizard-views-0.7/src/test/groovy/ViewRenderTest.groovy b/instrumentation/dropwizard-views-0.7/src/test/groovy/ViewRenderTest.groovy deleted file mode 100644 index 042ee9e3df..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/test/groovy/ViewRenderTest.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.dropwizard.views.View -import io.dropwizard.views.freemarker.FreemarkerViewRenderer -import io.dropwizard.views.mustache.MustacheViewRenderer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.nio.charset.StandardCharsets - -class ViewRenderTest extends AgentTestRunner { - - def "render #template succeeds with span"() { - setup: - def outputStream = new ByteArrayOutputStream() - - when: - runUnderTrace("parent") { - renderer.render(view, Locale.ENGLISH, outputStream) - } - - then: - outputStream.toString().contains("This is an example of a view") - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name "Render $template" - childOf span(0) - } - } - } - - where: - renderer | template - new FreemarkerViewRenderer() | "/views/ftl/utf8.ftl" - new MustacheViewRenderer() | "/views/mustache/utf8.mustache" - new FreemarkerViewRenderer() | "/views/ftl/utf8.ftl" - new MustacheViewRenderer() | "/views/mustache/utf8.mustache" - - view = new View(template, StandardCharsets.UTF_8) {} - } -} diff --git a/instrumentation/dropwizard-views-0.7/src/test/resources/views/ftl/iso88591.ftl b/instrumentation/dropwizard-views-0.7/src/test/resources/views/ftl/iso88591.ftl deleted file mode 100644 index be7e5c9a75..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/test/resources/views/ftl/iso88591.ftl +++ /dev/null @@ -1,10 +0,0 @@ - - - -

This is an example of a view containing ISO-8859-1 characters

- -¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ - - - - diff --git a/instrumentation/dropwizard-views-0.7/src/test/resources/views/ftl/utf8.ftl b/instrumentation/dropwizard-views-0.7/src/test/resources/views/ftl/utf8.ftl deleted file mode 100644 index 86d499e6d1..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/test/resources/views/ftl/utf8.ftl +++ /dev/null @@ -1,9 +0,0 @@ - - - -

This is an example of a view containing UTF-8 characters

- -€€€€€€€€€€€€€€€€€€ - - - \ No newline at end of file diff --git a/instrumentation/dropwizard-views-0.7/src/test/resources/views/mustache/iso88591.mustache b/instrumentation/dropwizard-views-0.7/src/test/resources/views/mustache/iso88591.mustache deleted file mode 100644 index be7e5c9a75..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/test/resources/views/mustache/iso88591.mustache +++ /dev/null @@ -1,10 +0,0 @@ - - - -

This is an example of a view containing ISO-8859-1 characters

- -¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ - - - - diff --git a/instrumentation/dropwizard-views-0.7/src/test/resources/views/mustache/utf8.mustache b/instrumentation/dropwizard-views-0.7/src/test/resources/views/mustache/utf8.mustache deleted file mode 100644 index 86d499e6d1..0000000000 --- a/instrumentation/dropwizard-views-0.7/src/test/resources/views/mustache/utf8.mustache +++ /dev/null @@ -1,9 +0,0 @@ - - - -

This is an example of a view containing UTF-8 characters

- -€€€€€€€€€€€€€€€€€€ - - - \ No newline at end of file diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/elasticsearch-rest-5.0.gradle b/instrumentation/elasticsearch/elasticsearch-rest-5.0/elasticsearch-rest-5.0.gradle deleted file mode 100644 index fef394519c..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/elasticsearch-rest-5.0.gradle +++ /dev/null @@ -1,45 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply plugin: 'org.unbroken-dome.test-sets' - -muzzle { - pass { - group = "org.elasticsearch.client" - module = "rest" - versions = "[5.0,6.4)" - assertInverse = true - } - - pass { - group = "org.elasticsearch.client" - module = "elasticsearch-rest-client" - versions = "[5.0,6.4)" - } -} - -testSets { - latestDepTest -} - -dependencies { - compileOnly group: 'org.elasticsearch.client', name: 'rest', version: '5.0.0' - - implementation project(':instrumentation:elasticsearch:elasticsearch-rest-common') - - testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-4.0') - testImplementation project(':instrumentation:apache-httpasyncclient-4.0') - - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0' - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0' - - testImplementation group: 'org.elasticsearch.client', name: 'rest', version: '5.0.0' - testImplementation group: 'org.elasticsearch', name: 'elasticsearch', version: '5.0.0' - testImplementation group: 'org.elasticsearch.plugin', name: 'transport-netty3-client', version: '5.0.0' - - latestDepTestImplementation group: 'org.elasticsearch.client', name: 'elasticsearch-rest-client', version: '6.3.+' - latestDepTestImplementation group: 'org.elasticsearch', name: 'elasticsearch', version: '6.3.+' - latestDepTestImplementation group: 'org.elasticsearch.plugin', name: 'transport-netty4-client', version: '6.3.+' -} - -configurations.latestDepTestImplementation { - exclude group: "org.elasticsearch.client", module: "rest" -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy index 9ab7c79e1e..03ca2e0420 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy @@ -6,9 +6,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import groovy.json.JsonSlurper +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.apache.http.HttpHost import org.apache.http.client.config.RequestConfig import org.apache.http.util.EntityUtils diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/Elasticsearch5RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/Elasticsearch5RestClientTest.groovy index 22e6f68624..36440b330d 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/Elasticsearch5RestClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/Elasticsearch5RestClientTest.groovy @@ -7,9 +7,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING import groovy.json.JsonSlurper +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.apache.http.HttpHost import org.apache.http.client.config.RequestConfig import org.apache.http.util.EntityUtils diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy deleted file mode 100644 index 03ca2e0420..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import groovy.json.JsonSlurper -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.http.HttpHost -import org.apache.http.client.config.RequestConfig -import org.apache.http.util.EntityUtils -import org.elasticsearch.client.Response -import org.elasticsearch.client.RestClient -import org.elasticsearch.client.RestClientBuilder -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.http.HttpServerTransport -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty4Plugin -import spock.lang.Shared - -class Elasticsearch6RestClientTest extends AgentTestRunner { - @Shared - TransportAddress httpTransportAddress - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - @Shared - RestClient client - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put("cluster.name", clusterName) - .build() - testNode = new Node(InternalSettingsPreparer.prepareEnvironment(settings, null), [Netty4Plugin]) - testNode.start() - httpTransportAddress = testNode.injector().getInstance(HttpServerTransport).boundAddress().publishAddress() - - client = RestClient.builder(new HttpHost(httpTransportAddress.address, httpTransportAddress.port)) - .setMaxRetryTimeoutMillis(Integer.MAX_VALUE) - .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { - @Override - RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) { - return builder.setConnectTimeout(Integer.MAX_VALUE).setSocketTimeout(Integer.MAX_VALUE) - } - }) - .build() - - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - Response response = client.performRequest("GET", "_cluster/health") - - Map result = new JsonSlurper().parseText(EntityUtils.toString(response.entity)) - - expect: - result.status == "green" - - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET _cluster/health" - kind CLIENT - hasNoParent() - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" httpTransportAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" httpTransportAddress.port - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GET _cluster/health" - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - } - } - } - } - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentationModule.java deleted file mode 100644 index 92d2a4dd88..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/Elasticsearch5RestClientInstrumentationModule.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.elasticsearch.client.ResponseListener; - -@AutoService(InstrumentationModule.class) -public class Elasticsearch5RestClientInstrumentationModule extends InstrumentationModule { - public Elasticsearch5RestClientInstrumentationModule() { - super("elasticsearch-rest", "elasticsearch-rest-5.0", "elasticsearch"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new RestClientInstrumentation()); - } - - public static class RestClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.elasticsearch.client.RestClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(namedOneOf("performRequestAsync", "performRequestAsyncNoCatch")) - .and(takesArguments(7)) - .and(takesArgument(0, named("java.lang.String"))) // method - .and(takesArgument(1, named("java.lang.String"))) // endpoint - .and(takesArgument(5, named("org.elasticsearch.client.ResponseListener"))), - Elasticsearch5RestClientInstrumentationModule.class.getName() - + "$ElasticsearchRestClientAdvice"); - } - } - - public static class ElasticsearchRestClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) String method, - @Advice.Argument(1) String endpoint, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Argument(value = 5, readOnly = false) ResponseListener responseListener) { - - span = tracer().startSpan(null, method + " " + endpoint); - scope = tracer().startScope(span); - - tracer().onRequest(span, method, endpoint); - responseListener = new RestResponseListener(responseListener, span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/RestResponseListener.java b/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/RestResponseListener.java deleted file mode 100644 index aaf8156534..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/RestResponseListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; - -public class RestResponseListener implements ResponseListener { - - private final ResponseListener listener; - private final Span span; - - public RestResponseListener(ResponseListener listener, Span span) { - this.listener = listener; - this.span = span; - } - - @Override - public void onSuccess(Response response) { - if (response.getHost() != null) { - tracer().onResponse(span, response); - } - tracer().end(span); - - listener.onSuccess(response); - } - - @Override - public void onFailure(Exception e) { - tracer().endExceptionally(span, e); - listener.onFailure(e); - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/test/groovy/Elasticsearch5RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/test/groovy/Elasticsearch5RestClientTest.groovy deleted file mode 100644 index 36440b330d..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/src/test/groovy/Elasticsearch5RestClientTest.groovy +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import groovy.json.JsonSlurper -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.http.HttpHost -import org.apache.http.client.config.RequestConfig -import org.apache.http.util.EntityUtils -import org.elasticsearch.client.Response -import org.elasticsearch.client.RestClient -import org.elasticsearch.client.RestClientBuilder -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.env.Environment -import org.elasticsearch.http.HttpServerTransport -import org.elasticsearch.node.Node -import org.elasticsearch.node.internal.InternalSettingsPreparer -import org.elasticsearch.transport.Netty3Plugin -import spock.lang.Shared - -class Elasticsearch5RestClientTest extends AgentTestRunner { - @Shared - TransportAddress httpTransportAddress - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - @Shared - static RestClient client - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]) - testNode.start() - httpTransportAddress = testNode.injector().getInstance(HttpServerTransport).boundAddress().publishAddress() - - client = RestClient.builder(new HttpHost(httpTransportAddress.address, httpTransportAddress.port)) - .setMaxRetryTimeoutMillis(Integer.MAX_VALUE) - .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { - @Override - RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) { - return builder.setConnectTimeout(Integer.MAX_VALUE).setSocketTimeout(Integer.MAX_VALUE) - } - }) - .build() - - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - Response response = client.performRequest("GET", "_cluster/health") - - Map result = new JsonSlurper().parseText(EntityUtils.toString(response.entity)) - - expect: - result.status == "green" - - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET _cluster/health" - kind CLIENT - hasNoParent() - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" httpTransportAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" httpTransportAddress.port - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GET _cluster/health" - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - } - } - } - } - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/elasticsearch-rest-6.4.gradle b/instrumentation/elasticsearch/elasticsearch-rest-6.4/elasticsearch-rest-6.4.gradle deleted file mode 100644 index e1d479e183..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/elasticsearch-rest-6.4.gradle +++ /dev/null @@ -1,45 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply plugin: 'org.unbroken-dome.test-sets' - -muzzle { - pass { - group = "org.elasticsearch.client" - module = "elasticsearch-rest-client" - versions = "[6.4,)" - assertInverse = true - } - - fail { - group = "org.elasticsearch.client" - module = "rest" - versions = "(,)" - } -} - -testSets { - latestDepTest -} - -dependencies { - compileOnly group: 'org.elasticsearch.client', name: 'elasticsearch-rest-client', version: '6.4.0' - - implementation project(':instrumentation:elasticsearch:elasticsearch-rest-common') - - testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-4.0') - testImplementation project(':instrumentation:apache-httpasyncclient-4.0') - // Netty is used, but it adds complexity to the tests since we're using embedded ES. - //testImplementation project(':instrumentation:netty:netty-4.1') - - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0' - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0' - - testImplementation group: 'org.elasticsearch.client', name: 'elasticsearch-rest-client', version: '6.4.0' - testImplementation group: 'org.elasticsearch', name: 'elasticsearch', version: '6.4.0' - testImplementation group: 'org.elasticsearch.plugin', name: 'transport-netty4-client', version: '6.4.0' - - // TODO: The tests are incompatible with 7.x. The instrumentation may be as well. - latestDepTestImplementation group: 'org.elasticsearch.client', name: 'elasticsearch-rest-client', version: '6.+' - latestDepTestImplementation group: 'org.elasticsearch.client', name: 'transport', version: '6.+' - latestDepTestImplementation group: 'org.elasticsearch', name: 'elasticsearch', version: '6.+' - latestDepTestImplementation group: 'org.elasticsearch.plugin', name: 'transport-netty4-client', version: '6.+' -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy index dbfd95944a..b4f1e6a5e8 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy @@ -6,9 +6,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import groovy.json.JsonSlurper +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.apache.http.HttpHost import org.apache.http.client.config.RequestConfig import org.apache.http.util.EntityUtils diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/groovy/Elasticsearch6RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/groovy/Elasticsearch6RestClientTest.groovy index 71e5a9bbb3..a6a2c82bd2 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/groovy/Elasticsearch6RestClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/groovy/Elasticsearch6RestClientTest.groovy @@ -6,9 +6,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import groovy.json.JsonSlurper +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.apache.http.HttpHost import org.apache.http.client.config.RequestConfig import org.apache.http.util.EntityUtils diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy deleted file mode 100644 index b4f1e6a5e8..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/latestDepTest/groovy/Elasticsearch6RestClientTest.groovy +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import groovy.json.JsonSlurper -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.http.HttpHost -import org.apache.http.client.config.RequestConfig -import org.apache.http.util.EntityUtils -import org.elasticsearch.client.Request -import org.elasticsearch.client.Response -import org.elasticsearch.client.RestClient -import org.elasticsearch.client.RestClientBuilder -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.env.Environment -import org.elasticsearch.http.HttpServerTransport -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.plugins.Plugin -import org.elasticsearch.transport.Netty4Plugin -import spock.lang.Shared - -class Elasticsearch6RestClientTest extends AgentTestRunner { - - @Shared - TransportAddress httpTransportAddress - @Shared - Node testNode - @Shared - File esWorkingDir - - @Shared - RestClient client - @Shared - String clusterName = UUID.randomUUID().toString() - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put("cluster.name", clusterName) - .build() - testNode = new TestNode(InternalSettingsPreparer.prepareEnvironment(settings, null), [Netty4Plugin]) - testNode.start() - httpTransportAddress = testNode.injector().getInstance(HttpServerTransport).boundAddress().publishAddress() - - client = RestClient.builder(new HttpHost(httpTransportAddress.address, httpTransportAddress.port)) - .setMaxRetryTimeoutMillis(Integer.MAX_VALUE) - .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { - @Override - RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) { - return builder.setConnectTimeout(Integer.MAX_VALUE).setSocketTimeout(Integer.MAX_VALUE) - } - }) - .build() - - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - Request request = new Request("GET", "_cluster/health") - Response response = client.performRequest(request) - - Map result = new JsonSlurper().parseText(EntityUtils.toString(response.entity)) - - expect: - result.status == "green" - - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET _cluster/health" - kind CLIENT - hasNoParent() - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" httpTransportAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" httpTransportAddress.port - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GET _cluster/health" - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - } - } - } - } - } - - static class TestNode extends Node { - TestNode(Environment environment, Collection> classpathPlugins) { - super(environment, classpathPlugins, false) - } - - @Override - protected void registerDerivedNodeNameWithLogger(String nodeName) {} - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentationModule.java deleted file mode 100644 index 87e54b901e..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/Elasticsearch6RestClientInstrumentationModule.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v6_4; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.elasticsearch.client.Request; -import org.elasticsearch.client.ResponseListener; - -@AutoService(InstrumentationModule.class) -public class Elasticsearch6RestClientInstrumentationModule extends InstrumentationModule { - public Elasticsearch6RestClientInstrumentationModule() { - super("elasticsearch-rest", "elasticsearch-rest-6.0", "elasticsearch"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new RestClientInstrumentation()); - } - - public static class RestClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.elasticsearch.client.RestClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("performRequestAsyncNoCatch")) - .and(takesArguments(2)) - .and(takesArgument(0, named("org.elasticsearch.client.Request"))) - .and(takesArgument(1, named("org.elasticsearch.client.ResponseListener"))), - Elasticsearch6RestClientInstrumentationModule.class.getName() - + "$ElasticsearchRestClientAdvice"); - } - } - - public static class ElasticsearchRestClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Request request, - @Advice.Argument(value = 1, readOnly = false) ResponseListener responseListener, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - span = tracer().startSpan(null, request.getMethod() + " " + request.getEndpoint()); - scope = tracer().startScope(span); - - tracer().onRequest(span, request.getMethod(), request.getEndpoint()); - responseListener = new RestResponseListener(responseListener, span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/RestResponseListener.java b/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/RestResponseListener.java deleted file mode 100644 index 1610bbcc68..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/RestResponseListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v6_4; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import org.elasticsearch.client.Response; -import org.elasticsearch.client.ResponseListener; - -public class RestResponseListener implements ResponseListener { - - private final ResponseListener listener; - private final Span span; - - public RestResponseListener(ResponseListener listener, Span span) { - this.listener = listener; - this.span = span; - } - - @Override - public void onSuccess(Response response) { - if (response.getHost() != null) { - tracer().onResponse(span, response); - } - tracer().end(span); - - listener.onSuccess(response); - } - - @Override - public void onFailure(Exception e) { - tracer().endExceptionally(span, e); - listener.onFailure(e); - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/test/groovy/Elasticsearch6RestClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/test/groovy/Elasticsearch6RestClientTest.groovy deleted file mode 100644 index a6a2c82bd2..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/src/test/groovy/Elasticsearch6RestClientTest.groovy +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import groovy.json.JsonSlurper -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.http.HttpHost -import org.apache.http.client.config.RequestConfig -import org.apache.http.util.EntityUtils -import org.elasticsearch.client.Response -import org.elasticsearch.client.RestClient -import org.elasticsearch.client.RestClientBuilder -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.http.HttpServerTransport -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty4Plugin -import spock.lang.Shared - -class Elasticsearch6RestClientTest extends AgentTestRunner { - @Shared - TransportAddress httpTransportAddress - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - @Shared - RestClient client - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put("cluster.name", clusterName) - .build() - testNode = new Node(InternalSettingsPreparer.prepareEnvironment(settings, null), [Netty4Plugin]) - testNode.start() - httpTransportAddress = testNode.injector().getInstance(HttpServerTransport).boundAddress().publishAddress() - - client = RestClient.builder(new HttpHost(httpTransportAddress.address, httpTransportAddress.port)) - .setMaxRetryTimeoutMillis(Integer.MAX_VALUE) - .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { - @Override - RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) { - return builder.setConnectTimeout(Integer.MAX_VALUE).setSocketTimeout(Integer.MAX_VALUE) - } - }) - .build() - - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - Response response = client.performRequest("GET", "_cluster/health") - - Map result = new JsonSlurper().parseText(EntityUtils.toString(response.entity)) - - expect: - result.status == "green" - - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET _cluster/health" - kind CLIENT - hasNoParent() - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" httpTransportAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" httpTransportAddress.port - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GET _cluster/health" - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.HTTP_URL.key()}" "_cluster/health" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - } - } - } - } - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common/elasticsearch-rest-common.gradle b/instrumentation/elasticsearch/elasticsearch-rest-common/elasticsearch-rest-common.gradle deleted file mode 100644 index f2ed3bb1b8..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-common/elasticsearch-rest-common.gradle +++ /dev/null @@ -1,5 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - compileOnly group: 'org.elasticsearch.client', name: 'rest', version: '5.0.0' -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java b/instrumentation/elasticsearch/elasticsearch-rest-common/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java deleted file mode 100644 index 09ec9d1b90..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-common/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestClientTracer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import java.net.InetSocketAddress; -import org.elasticsearch.client.Response; - -public class ElasticsearchRestClientTracer extends DatabaseClientTracer { - private static final ElasticsearchRestClientTracer TRACER = new ElasticsearchRestClientTracer(); - - public static ElasticsearchRestClientTracer tracer() { - return TRACER; - } - - public Span onRequest(Span span, String method, String endpoint) { - span.setAttribute(SemanticAttributes.HTTP_METHOD, method); - span.setAttribute(SemanticAttributes.HTTP_URL, endpoint); - return span; - } - - public Span onResponse(Span span, Response response) { - if (response != null && response.getHost() != null) { - NetPeerUtils.setNetPeer(span, response.getHost().getHostName(), null); - span.setAttribute(SemanticAttributes.NET_PEER_PORT, (long) response.getHost().getPort()); - } - return span; - } - - @Override - protected void onStatement(Span span, String statement) { - span.setAttribute(SemanticAttributes.DB_OPERATION, statement); - } - - @Override - protected String normalizeQuery(String query) { - return query; - } - - @Override - protected String dbSystem(Void connection) { - return "elasticsearch"; - } - - @Override - protected InetSocketAddress peerAddress(Void connection) { - return null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.elasticsearch"; - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/elasticsearch-transport-5.0.gradle b/instrumentation/elasticsearch/elasticsearch-transport-5.0/elasticsearch-transport-5.0.gradle deleted file mode 100644 index f32f9921de..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/elasticsearch-transport-5.0.gradle +++ /dev/null @@ -1,33 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.elasticsearch.client" - module = "transport" - versions = "[5.0.0,5.3.0)" - assertInverse = true - } - pass { - group = "org.elasticsearch" - module = "elasticsearch" - versions = "[5.0.0,5.3.0)" - assertInverse = true - } -} - -dependencies { - compileOnly group: 'org.elasticsearch.client', name: 'transport', version: '5.0.0' - - implementation project(':instrumentation:elasticsearch:elasticsearch-transport-common') - - // Ensure no cross interference - testImplementation project(':instrumentation:elasticsearch:elasticsearch-rest-5.0') - testImplementation project(':instrumentation:apache-httpasyncclient-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0' - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0' - - testImplementation group: 'org.elasticsearch.plugin', name: 'transport-netty3-client', version: '5.0.0' - testImplementation group: 'org.elasticsearch.client', name: 'transport', version: '5.0.0' -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5NodeClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5NodeClientTest.groovy index af01a68452..6803443213 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5NodeClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5NodeClientTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest import org.elasticsearch.common.io.FileSystemUtils import org.elasticsearch.common.settings.Settings diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5TransportClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5TransportClientTest.groovy index a0907443b8..e4ff6bd79f 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5TransportClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.0/javaagent/src/test/groovy/Elasticsearch5TransportClientTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest import org.elasticsearch.client.transport.TransportClient import org.elasticsearch.common.io.FileSystemUtils diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentationModule.java deleted file mode 100644 index 144d88e262..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/Elasticsearch5TransportClientInstrumentationModule.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.elasticsearch.action.Action; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; - -@AutoService(InstrumentationModule.class) -public class Elasticsearch5TransportClientInstrumentationModule extends InstrumentationModule { - public Elasticsearch5TransportClientInstrumentationModule() { - super("elasticsearch-transport", "elasticsearch-transport-5.0", "elasticsearch"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AbstractClientInstrumentation()); - } - - public static class AbstractClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - // If we want to be more generic, we could instrument the interface instead: - // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) - return named("org.elasticsearch.client.support.AbstractClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArgument(0, named("org.elasticsearch.action.Action"))) - .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) - .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), - Elasticsearch5TransportClientInstrumentationModule.class.getName() - + "$ElasticsearchTransportClientAdvice"); - } - } - - public static class ElasticsearchTransportClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Action action, - @Advice.Argument(1) ActionRequest actionRequest, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Argument(value = 2, readOnly = false) - ActionListener actionListener) { - - span = tracer().startSpan(null, action); - scope = tracer().startScope(span); - - tracer().onRequest(span, action.getClass(), actionRequest.getClass()); - actionListener = new TransportActionListener<>(actionRequest, actionListener, span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/TransportActionListener.java b/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/TransportActionListener.java deleted file mode 100644 index ce2809609b..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_0/TransportActionListener.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.action.DocumentRequest; -import org.elasticsearch.action.IndicesRequest; -import org.elasticsearch.action.bulk.BulkShardResponse; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.support.broadcast.BroadcastResponse; -import org.elasticsearch.action.support.nodes.BaseNodesResponse; -import org.elasticsearch.action.support.replication.ReplicationResponse; - -public class TransportActionListener implements ActionListener { - - private final ActionListener listener; - private final Span span; - - public TransportActionListener( - ActionRequest actionRequest, ActionListener listener, Span span) { - this.listener = listener; - this.span = span; - onRequest(actionRequest); - } - - private void onRequest(ActionRequest request) { - if (request instanceof IndicesRequest) { - IndicesRequest req = (IndicesRequest) request; - String[] indices = req.indices(); - if (indices != null && indices.length > 0) { - span.setAttribute("elasticsearch.request.indices", String.join(",", indices)); - } - } - if (request instanceof SearchRequest) { - SearchRequest req = (SearchRequest) request; - String[] types = req.types(); - if (types != null && types.length > 0) { - span.setAttribute("elasticsearch.request.search.types", String.join(",", types)); - } - } - if (request instanceof DocumentRequest) { - DocumentRequest req = (DocumentRequest) request; - span.setAttribute("elasticsearch.request.write.type", req.type()); - span.setAttribute("elasticsearch.request.write.routing", req.routing()); - } - } - - @Override - public void onResponse(T response) { - if (response.remoteAddress() != null) { - NetPeerUtils.setNetPeer( - span, response.remoteAddress().getHost(), response.remoteAddress().getAddress()); - span.setAttribute( - SemanticAttributes.NET_PEER_PORT, (long) response.remoteAddress().getPort()); - } - - if (response instanceof GetResponse) { - GetResponse resp = (GetResponse) response; - span.setAttribute("elasticsearch.type", resp.getType()); - span.setAttribute("elasticsearch.id", resp.getId()); - span.setAttribute("elasticsearch.version", resp.getVersion()); - } - - if (response instanceof BroadcastResponse) { - BroadcastResponse resp = (BroadcastResponse) response; - span.setAttribute("elasticsearch.shard.broadcast.total", resp.getTotalShards()); - span.setAttribute("elasticsearch.shard.broadcast.successful", resp.getSuccessfulShards()); - span.setAttribute("elasticsearch.shard.broadcast.failed", resp.getFailedShards()); - } - - if (response instanceof ReplicationResponse) { - ReplicationResponse resp = (ReplicationResponse) response; - span.setAttribute("elasticsearch.shard.replication.total", resp.getShardInfo().getTotal()); - span.setAttribute( - "elasticsearch.shard.replication.successful", resp.getShardInfo().getSuccessful()); - span.setAttribute("elasticsearch.shard.replication.failed", resp.getShardInfo().getFailed()); - } - - if (response instanceof IndexResponse) { - span.setAttribute( - "elasticsearch.response.status", ((IndexResponse) response).status().getStatus()); - } - - if (response instanceof BulkShardResponse) { - BulkShardResponse resp = (BulkShardResponse) response; - span.setAttribute("elasticsearch.shard.bulk.id", resp.getShardId().getId()); - span.setAttribute("elasticsearch.shard.bulk.index", resp.getShardId().getIndexName()); - } - - if (response instanceof BaseNodesResponse) { - BaseNodesResponse resp = (BaseNodesResponse) response; - if (resp.hasFailures()) { - span.setAttribute("elasticsearch.node.failures", resp.failures().size()); - } - span.setAttribute("elasticsearch.node.cluster.name", resp.getClusterName().value()); - } - - tracer().end(span); - listener.onResponse(response); - } - - @Override - public void onFailure(Exception e) { - tracer().endExceptionally(span, e); - listener.onFailure(e); - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/test/groovy/Elasticsearch5NodeClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/test/groovy/Elasticsearch5NodeClientTest.groovy deleted file mode 100644 index 6803443213..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/test/groovy/Elasticsearch5NodeClientTest.groovy +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.env.Environment -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.Node -import org.elasticsearch.node.internal.InternalSettingsPreparer -import org.elasticsearch.transport.Netty3Plugin -import spock.lang.Shared - -class Elasticsearch5NodeClientTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - def client = testNode.client() - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]) - testNode.start() - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - testNode.client().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - def result = client.admin().cluster().health(new ClusterHealthRequest()) - - def status = result.get().status - - expect: - status.name() == "GREEN" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - } - } - - def "test elasticsearch error"() { - when: - client.prepareGet(indexName, indexType, id).get() - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GetAction" - errored true - errorEvent IndexNotFoundException, "no such index" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - indexType = "test-type" - id = "1" - } - - def "test elasticsearch get"() { - setup: - assert TEST_WRITER.traces == [] - def indexResult = client.admin().indices().prepareCreate(indexName).get() - TEST_WRITER.waitForTraces(1) - - expect: - indexResult.acknowledged - TEST_WRITER.traces.size() == 1 - - when: - client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - def emptyResult = client.prepareGet(indexName, indexType, id).get() - - then: - !emptyResult.isExists() - emptyResult.id == id - emptyResult.type == indexType - emptyResult.index == indexName - - when: - def createResult = client.prepareIndex(indexName, indexType, id).setSource([:]).get() - - then: - createResult.id == id - createResult.type == indexType - createResult.index == indexName - createResult.status().status == 201 - - when: - def result = client.prepareGet(indexName, indexType, id).get() - - then: - result.isExists() - result.id == id - result.type == indexType - result.index == indexName - - and: - assertTraces(5) { - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - trace(2, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version"(-1) - } - } - } - trace(3, 2) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.total" 2 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.failed" 0 - } - } - span(1) { - name "PutMappingAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(4, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version" 1 - } - } - } - } - - cleanup: - client.admin().indices().prepareDelete(indexName).get() - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/test/groovy/Elasticsearch5TransportClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/test/groovy/Elasticsearch5TransportClientTest.groovy deleted file mode 100644 index e4ff6bd79f..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.0/src/test/groovy/Elasticsearch5TransportClientTest.groovy +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest -import org.elasticsearch.client.transport.TransportClient -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.env.Environment -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.Node -import org.elasticsearch.node.internal.InternalSettingsPreparer -import org.elasticsearch.transport.Netty3Plugin -import org.elasticsearch.transport.RemoteTransportException -import org.elasticsearch.transport.TransportService -import org.elasticsearch.transport.client.PreBuiltTransportClient -import spock.lang.Shared - -class Elasticsearch5TransportClientTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - @Shared - TransportAddress tcpPublishAddress - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - @Shared - TransportClient client - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]) - testNode.start() - tcpPublishAddress = testNode.injector().getInstance(TransportService).boundAddress().publishAddress() - - client = new PreBuiltTransportClient( - Settings.builder() - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - ) - client.addTransportAddress(tcpPublishAddress) - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - def result = client.admin().cluster().health(new ClusterHealthRequest()) - - def status = result.get().status - - expect: - status.name() == "GREEN" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.host - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - } - } - - def "test elasticsearch error"() { - when: - client.prepareGet(indexName, indexType, id).get() - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GetAction" - kind CLIENT - errored true - errorEvent RemoteTransportException, String - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - indexType = "test-type" - id = "1" - } - - def "test elasticsearch get"() { - setup: - assert TEST_WRITER.traces == [] - def indexResult = client.admin().indices().prepareCreate(indexName).get() - TEST_WRITER.waitForTraces(1) - - expect: - indexResult.acknowledged - TEST_WRITER.traces.size() == 1 - - when: - def emptyResult = client.prepareGet(indexName, indexType, id).get() - - then: - !emptyResult.isExists() - emptyResult.id == id - emptyResult.type == indexType - emptyResult.index == indexName - - when: - def createResult = client.prepareIndex(indexName, indexType, id).setSource([:]).get() - - then: - createResult.id == id - createResult.type == indexType - createResult.index == indexName - createResult.status().status == 201 - - when: - def result = client.prepareGet(indexName, indexType, id).get() - - then: - result.isExists() - result.id == id - result.type == indexType - result.index == indexName - - and: - assertTraces(5) { - sortTraces { - // IndexAction and PutMappingAction run in separate threads and so their order is not always the same - if (traces[2][0].name == "IndexAction") { - def tmp = traces[2] - traces[2] = traces[3] - traces[3] = tmp - } - } - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.host - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.host - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version"(-1) - } - } - } - trace(2, 1) { - span(0) { - name "PutMappingAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(3, 1) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.host - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.total" 2 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.failed" 0 - } - } - } - trace(4, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version" 1 - } - } - } - } - - cleanup: - client.admin().indices().prepareDelete(indexName).get() - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/elasticsearch-transport-5.3.gradle b/instrumentation/elasticsearch/elasticsearch-transport-5.3/elasticsearch-transport-5.3.gradle deleted file mode 100644 index 9352ee702b..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/elasticsearch-transport-5.3.gradle +++ /dev/null @@ -1,38 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.elasticsearch.client" - module = "transport" - versions = "[5.3.0,6.0.0)" - assertInverse = true - } - pass { - group = "org.elasticsearch" - module = "elasticsearch" - versions = "[5.3.0,6.0.0)" - assertInverse = true - } -} - -dependencies { - library group: 'org.elasticsearch.client', name: 'transport', version: '5.3.0' - - implementation project(':instrumentation:elasticsearch:elasticsearch-transport-common') - - testImplementation project(':instrumentation:apache-httpasyncclient-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:spring:spring-data-1.8:javaagent') - - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0' - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0' - - testLibrary group: 'org.elasticsearch.plugin', name: 'transport-netty3-client', version: '5.3.0' - - // Unfortunately this will bump the transport version up to 5.5.0. - testLibrary group: 'org.springframework.data', name: 'spring-data-elasticsearch', version: '3.0.0.RELEASE' - - latestDepTestLibrary group: 'org.elasticsearch.plugin', name: 'transport-netty3-client', version: '5.+' - latestDepTestLibrary group: 'org.elasticsearch.client', name: 'transport', version: '5.+' - latestDepTestLibrary group: 'org.springframework.data', name: 'spring-data-elasticsearch', version: '3.0.+' -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53NodeClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53NodeClientTest.groovy index ebca87281d..b0ee8594e9 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53NodeClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53NodeClientTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest import org.elasticsearch.common.io.FileSystemUtils import org.elasticsearch.common.settings.Settings diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53TransportClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53TransportClientTest.groovy index 7c630e80b8..08267a6019 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53TransportClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/Elasticsearch53TransportClientTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest import org.elasticsearch.client.transport.TransportClient import org.elasticsearch.common.io.FileSystemUtils diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy index ebee6d27bb..3d4c46413c 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy @@ -5,12 +5,12 @@ package springdata -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT import static io.opentelemetry.api.trace.Span.Kind.INTERNAL +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import java.lang.reflect.InvocationHandler import java.lang.reflect.Method import java.lang.reflect.Proxy diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy index 2226e98e7b..b91bad996e 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy @@ -5,13 +5,13 @@ package springdata -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING import com.google.common.collect.ImmutableSet -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import java.util.concurrent.atomic.AtomicLong import org.elasticsearch.action.search.SearchResponse import org.elasticsearch.common.io.FileSystemUtils diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentationModule.java deleted file mode 100644 index 00428d81ba..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/Elasticsearch53TransportClientInstrumentationModule.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_3; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.elasticsearch.action.Action; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; - -/** Beginning in version 5.3.0, DocumentRequest was renamed to DocWriteRequest. */ -@AutoService(InstrumentationModule.class) -public class Elasticsearch53TransportClientInstrumentationModule extends InstrumentationModule { - public Elasticsearch53TransportClientInstrumentationModule() { - super("elasticsearch-transport", "elasticsearch-transport-5.3", "elasticsearch"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AbstractClientInstrumentation()); - } - - public static class AbstractClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - // If we want to be more generic, we could instrument the interface instead: - // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) - return named("org.elasticsearch.client.support.AbstractClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArgument(0, named("org.elasticsearch.action.Action"))) - .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) - .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), - Elasticsearch53TransportClientInstrumentationModule.class.getName() - + "$ElasticsearchTransportClientAdvice"); - } - } - - public static class ElasticsearchTransportClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Action action, - @Advice.Argument(1) ActionRequest actionRequest, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Argument(value = 2, readOnly = false) - ActionListener actionListener) { - - span = tracer().startSpan(null, action); - scope = tracer().startScope(span); - - tracer().onRequest(span, action.getClass(), actionRequest.getClass()); - actionListener = new TransportActionListener<>(actionRequest, actionListener, span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/TransportActionListener.java b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/TransportActionListener.java deleted file mode 100644 index b29c98d356..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/TransportActionListener.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v5_3; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.action.DocWriteRequest; -import org.elasticsearch.action.IndicesRequest; -import org.elasticsearch.action.bulk.BulkShardResponse; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.support.broadcast.BroadcastResponse; -import org.elasticsearch.action.support.nodes.BaseNodesResponse; -import org.elasticsearch.action.support.replication.ReplicationResponse; - -public class TransportActionListener implements ActionListener { - - private final ActionListener listener; - private final Span span; - - public TransportActionListener( - ActionRequest actionRequest, ActionListener listener, Span span) { - this.listener = listener; - this.span = span; - onRequest(actionRequest); - } - - private void onRequest(ActionRequest request) { - if (request instanceof IndicesRequest) { - IndicesRequest req = (IndicesRequest) request; - String[] indices = req.indices(); - if (indices != null && indices.length > 0) { - span.setAttribute("elasticsearch.request.indices", String.join(",", indices)); - } - } - if (request instanceof SearchRequest) { - SearchRequest req = (SearchRequest) request; - String[] types = req.types(); - if (types != null && types.length > 0) { - span.setAttribute("elasticsearch.request.search.types", String.join(",", types)); - } - } - if (request instanceof DocWriteRequest) { - DocWriteRequest req = (DocWriteRequest) request; - span.setAttribute("elasticsearch.request.write.type", req.type()); - span.setAttribute("elasticsearch.request.write.routing", req.routing()); - span.setAttribute("elasticsearch.request.write.version", req.version()); - } - } - - @Override - public void onResponse(T response) { - if (response.remoteAddress() != null) { - NetPeerUtils.setNetPeer( - span, response.remoteAddress().getHost(), response.remoteAddress().getAddress()); - span.setAttribute( - SemanticAttributes.NET_PEER_PORT, (long) response.remoteAddress().getPort()); - } - - if (response instanceof GetResponse) { - GetResponse resp = (GetResponse) response; - span.setAttribute("elasticsearch.type", resp.getType()); - span.setAttribute("elasticsearch.id", resp.getId()); - span.setAttribute("elasticsearch.version", resp.getVersion()); - } - - if (response instanceof BroadcastResponse) { - BroadcastResponse resp = (BroadcastResponse) response; - span.setAttribute("elasticsearch.shard.broadcast.total", resp.getTotalShards()); - span.setAttribute("elasticsearch.shard.broadcast.successful", resp.getSuccessfulShards()); - span.setAttribute("elasticsearch.shard.broadcast.failed", resp.getFailedShards()); - } - - if (response instanceof ReplicationResponse) { - ReplicationResponse resp = (ReplicationResponse) response; - span.setAttribute("elasticsearch.shard.replication.total", resp.getShardInfo().getTotal()); - span.setAttribute( - "elasticsearch.shard.replication.successful", resp.getShardInfo().getSuccessful()); - span.setAttribute("elasticsearch.shard.replication.failed", resp.getShardInfo().getFailed()); - } - - if (response instanceof IndexResponse) { - span.setAttribute( - "elasticsearch.response.status", ((IndexResponse) response).status().getStatus()); - } - - if (response instanceof BulkShardResponse) { - BulkShardResponse resp = (BulkShardResponse) response; - span.setAttribute("elasticsearch.shard.bulk.id", resp.getShardId().getId()); - span.setAttribute("elasticsearch.shard.bulk.index", resp.getShardId().getIndexName()); - } - - if (response instanceof BaseNodesResponse) { - BaseNodesResponse resp = (BaseNodesResponse) response; - if (resp.hasFailures()) { - span.setAttribute("elasticsearch.node.failures", resp.failures().size()); - } - span.setAttribute("elasticsearch.node.cluster.name", resp.getClusterName().value()); - } - - tracer().end(span); - listener.onResponse(response); - } - - @Override - public void onFailure(Exception e) { - tracer().endExceptionally(span, e); - listener.onFailure(e); - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/Elasticsearch53NodeClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/Elasticsearch53NodeClientTest.groovy deleted file mode 100644 index b0ee8594e9..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/Elasticsearch53NodeClientTest.groovy +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.env.Environment -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty3Plugin -import spock.lang.Shared - -class Elasticsearch53NodeClientTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - def client = testNode.client() - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]) - testNode.start() - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - testNode.client().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - def result = client.admin().cluster().health(new ClusterHealthRequest()) - - def status = result.get().status - - expect: - status.name() == "GREEN" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - } - } - - def "test elasticsearch error"() { - when: - client.prepareGet(indexName, indexType, id).get() - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GetAction" - kind CLIENT - errored true - errorEvent IndexNotFoundException, "no such index" - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - indexType = "test-type" - id = "1" - } - - def "test elasticsearch get"() { - setup: - assert TEST_WRITER.traces == [] - def indexResult = client.admin().indices().prepareCreate(indexName).get() - TEST_WRITER.waitForTraces(1) - - expect: - indexResult.acknowledged - TEST_WRITER.traces.size() == 1 - - when: - client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - def emptyResult = client.prepareGet(indexName, indexType, id).get() - - then: - !emptyResult.isExists() - emptyResult.id == id - emptyResult.type == indexType - emptyResult.index == indexName - - when: - def createResult = client.prepareIndex(indexName, indexType, id).setSource([:]).get() - - then: - createResult.id == id - createResult.type == indexType - createResult.index == indexName - createResult.status().status == 201 - - when: - def result = client.prepareGet(indexName, indexType, id).get() - - then: - result.isExists() - result.id == id - result.type == indexType - result.index == indexName - - and: - assertTraces(5) { - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - trace(2, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version"(-1) - } - } - } - trace(3, 2) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.total" 2 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.failed" 0 - } - } - span(1) { - name "PutMappingAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(4, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version" 1 - } - } - } - } - - cleanup: - client.admin().indices().prepareDelete(indexName).get() - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/Elasticsearch53TransportClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/Elasticsearch53TransportClientTest.groovy deleted file mode 100644 index 08267a6019..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/Elasticsearch53TransportClientTest.groovy +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest -import org.elasticsearch.client.transport.TransportClient -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.env.Environment -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty3Plugin -import org.elasticsearch.transport.RemoteTransportException -import org.elasticsearch.transport.TransportService -import org.elasticsearch.transport.client.PreBuiltTransportClient -import spock.lang.Shared - -class Elasticsearch53TransportClientTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - @Shared - TransportAddress tcpPublishAddress - - @Shared - Node testNode - @Shared - File esWorkingDir - - @Shared - TransportClient client - @Shared - String clusterName = UUID.randomUUID().toString() - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]) - testNode.start() - tcpPublishAddress = testNode.injector().getInstance(TransportService).boundAddress().publishAddress() - - client = new PreBuiltTransportClient( - Settings.builder() - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - ) - client.addTransportAddress(tcpPublishAddress) - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - def result = client.admin().cluster().health(new ClusterHealthRequest()) - - def status = result.get().status - - expect: - status.name() == "GREEN" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - } - } - - def "test elasticsearch error"() { - when: - client.prepareGet(indexName, indexType, id).get() - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GetAction" - kind CLIENT - errored true - errorEvent RemoteTransportException, String - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - indexType = "test-type" - id = "1" - } - - def "test elasticsearch get"() { - setup: - assert TEST_WRITER.traces == [] - def indexResult = client.admin().indices().prepareCreate(indexName).get() - TEST_WRITER.waitForTraces(1) - - expect: - indexResult.acknowledged - TEST_WRITER.traces.size() == 1 - - when: - def emptyResult = client.prepareGet(indexName, indexType, id).get() - - then: - !emptyResult.isExists() - emptyResult.id == id - emptyResult.type == indexType - emptyResult.index == indexName - - when: - def createResult = client.prepareIndex(indexName, indexType, id).setSource([:]).get() - - then: - createResult.id == id - createResult.type == indexType - createResult.index == indexName - createResult.status().status == 201 - - when: - def result = client.prepareGet(indexName, indexType, id).get() - - then: - result.isExists() - result.id == id - result.type == indexType - result.index == indexName - - and: - assertTraces(5) { - sortTraces { - // IndexAction and PutMappingAction run in separate threads and so their order is not always the same - if (traces[2][0].name == "IndexAction") { - def tmp = traces[2] - traces[2] = traces[3] - traces[3] = tmp - } - } - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version"(-1) - } - } - } - trace(2, 1) { - span(0) { - name "PutMappingAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(3, 1) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.total" 2 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.failed" 0 - } - } - } - trace(4, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" tcpPublishAddress.host == tcpPublishAddress.address ? null : tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version" 1 - } - } - } - } - - cleanup: - client.admin().indices().prepareDelete(indexName).get() - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Config.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Config.groovy deleted file mode 100644 index 5f51802f76..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Config.groovy +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.env.Environment -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty3Plugin -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration -import org.springframework.data.elasticsearch.core.ElasticsearchOperations -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate -import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories - -@Configuration -@EnableElasticsearchRepositories(basePackages = "springdata") -@ComponentScan(basePackages = "springdata") -class Config { - - @Bean - NodeBuilder nodeBuilder() { - return new NodeBuilder() - } - - @Bean - ElasticsearchOperations elasticsearchTemplate() { - def tmpDir = File.createTempFile("test-es-working-dir-", "") - tmpDir.delete() - tmpDir.mkdir() - tmpDir.deleteOnExit() - - System.addShutdownHook { - if (tmpDir != null) { - FileSystemUtils.deleteSubDirectories(tmpDir.toPath()) - tmpDir.delete() - } - } - - def settings = Settings.builder() - .put("http.enabled", "false") - .put("path.data", tmpDir.toString()) - .put("path.home", tmpDir.toString()) - .put("thread_pool.listener.size", 1) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .build() - - println "ES work dir: $tmpDir" - - return new ElasticsearchTemplate(new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]).start().client()) - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Doc.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Doc.groovy deleted file mode 100644 index b2b35f1037..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Doc.groovy +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import groovy.transform.EqualsAndHashCode -import org.springframework.data.annotation.Id -import org.springframework.data.elasticsearch.annotations.Document - -@Document(indexName = "test-index") -@EqualsAndHashCode -class Doc { - @Id - private String id = "1" - private String data = "some data" - - String getId() { - return id - } - - void setId(String id) { - this.id = id - } - - String getData() { - return data - } - - void setData(String data) { - this.data = data - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/DocRepository.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/DocRepository.groovy deleted file mode 100644 index dca62c1028..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/DocRepository.groovy +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import org.springframework.data.elasticsearch.repository.ElasticsearchRepository - -interface DocRepository extends ElasticsearchRepository {} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy deleted file mode 100644 index 3d4c46413c..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.lang.reflect.InvocationHandler -import java.lang.reflect.Method -import java.lang.reflect.Proxy -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import spock.lang.Shared - -class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { - // Setting up appContext & repo with @Shared doesn't allow - // spring-data instrumentation to applied. - // To change the timing without adding ugly checks everywhere - - // use a dynamic proxy. There's probably a more "groovy" way to do this. - - @Shared - DocRepository repo = Proxy.newProxyInstance( - getClass().getClassLoader(), - [DocRepository] as Class[], - new LazyProxyInvoker()) - - static class LazyProxyInvoker implements InvocationHandler { - def repo - - DocRepository getOrCreateRepository() { - if (repo != null) { - return repo - } - - def applicationContext = new AnnotationConfigApplicationContext(Config) - repo = applicationContext.getBean(DocRepository) - - return repo - } - - @Override - Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return method.invoke(getOrCreateRepository(), args) - } - } - - def setup() { - repo.refresh() - TEST_WRITER.clear() - runUnderTrace("delete") { - repo.deleteAll() - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - } - - def "test empty repo"() { - when: - def result = repo.findAll() - - then: - !result.iterator().hasNext() - - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "CrudRepository.findAll" - kind INTERNAL - attributes { - } - } - span(1) { - name "SearchAction" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "SearchAction" - "elasticsearch.action" "SearchAction" - "elasticsearch.request" "SearchRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.search.types" "doc" - } - } - } - } - - where: - indexName = "test-index" - } - - def "test CRUD"() { - when: - def doc = new Doc() - - then: - repo.index(doc) == doc - - and: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "ElasticsearchRepository.index" - kind INTERNAL - attributes { - } - } - span(1) { - name "IndexAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" "doc" - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.failed" 0 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.total" 2 - } - } - span(2) { - name "PutMappingAction" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - span(3) { - name "RefreshAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "RefreshAction" - "elasticsearch.action" "RefreshAction" - "elasticsearch.request" "RefreshRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.shard.broadcast.failed" 0 - "elasticsearch.shard.broadcast.successful" 5 - "elasticsearch.shard.broadcast.total" 10 - } - } - } - } - TEST_WRITER.clear() - - and: - repo.findById("1").get() == doc - - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "CrudRepository.findById" - kind INTERNAL - attributes { - } - } - span(1) { - name "GetAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" "doc" - "elasticsearch.id" "1" - "elasticsearch.version" Number - } - } - } - } - TEST_WRITER.clear() - - when: - doc.data = "other data" - - then: - repo.index(doc) == doc - repo.findById("1").get() == doc - - and: - assertTraces(2) { - trace(0, 3) { - span(0) { - name "ElasticsearchRepository.index" - kind INTERNAL - attributes { - } - } - span(1) { - name "IndexAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" "doc" - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 200 - "elasticsearch.shard.replication.failed" 0 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.total" 2 - } - } - span(2) { - name "RefreshAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "RefreshAction" - "elasticsearch.action" "RefreshAction" - "elasticsearch.request" "RefreshRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.shard.broadcast.failed" 0 - "elasticsearch.shard.broadcast.successful" 5 - "elasticsearch.shard.broadcast.total" 10 - } - } - } - trace(1, 2) { - span(0) { - name "CrudRepository.findById" - kind INTERNAL - attributes { - } - } - span(1) { - name "GetAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" "doc" - "elasticsearch.id" "1" - "elasticsearch.version" Number - } - } - } - } - TEST_WRITER.clear() - - when: - repo.deleteById("1") - - then: - !repo.findAll().iterator().hasNext() - - and: - assertTraces(2) { - trace(0, 3) { - span(0) { - name "CrudRepository.deleteById" - kind INTERNAL - attributes { - } - } - span(1) { - name "DeleteAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "DeleteAction" - "elasticsearch.action" "DeleteAction" - "elasticsearch.request" "DeleteRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" "doc" - "elasticsearch.request.write.version"(-3) - "elasticsearch.shard.replication.failed" 0 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.total" 2 - } - } - span(2) { - name "RefreshAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "RefreshAction" - "elasticsearch.action" "RefreshAction" - "elasticsearch.request" "RefreshRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.shard.broadcast.failed" 0 - "elasticsearch.shard.broadcast.successful" 5 - "elasticsearch.shard.broadcast.total" 10 - } - } - } - - trace(1, 2) { - span(0) { - name "CrudRepository.findAll" - kind INTERNAL - attributes { - } - } - span(1) { - name "SearchAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "SearchAction" - "elasticsearch.action" "SearchAction" - "elasticsearch.request" "SearchRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.search.types" "doc" - } - } - } - } - - where: - indexName = "test-index" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy deleted file mode 100644 index b91bad996e..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package springdata - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import com.google.common.collect.ImmutableSet -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.atomic.AtomicLong -import org.elasticsearch.action.search.SearchResponse -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.env.Environment -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.search.aggregations.bucket.nested.InternalNested -import org.elasticsearch.search.aggregations.bucket.terms.Terms -import org.elasticsearch.transport.Netty3Plugin -import org.springframework.data.elasticsearch.core.ElasticsearchTemplate -import org.springframework.data.elasticsearch.core.ResultsExtractor -import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder -import org.springframework.data.elasticsearch.core.query.NativeSearchQuery -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder -import spock.lang.Shared - -class Elasticsearch53SpringTemplateTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - // Some ES actions are not caused by clients and seem to just happen from time to time. - // We will just ignore these actions in traces. - // TODO: check if other ES tests need this protection and potentially pull this into global class - public static final Set IGNORED_ACTIONS = ImmutableSet.of("NodesStatsAction", "IndicesStatsAction") - - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - @Shared - ElasticsearchTemplate template - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put("transport.type", "netty3") - .put("http.type", "netty3") - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(new Environment(InternalSettingsPreparer.prepareSettings(settings)), [Netty3Plugin]) - testNode.start() - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - testNode.client().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - - template = new ElasticsearchTemplate(testNode.client()) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch error"() { - when: - template.refresh(indexName) - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RefreshAction" - kind CLIENT - errored true - errorEvent IndexNotFoundException, "no such index" - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "RefreshAction" - "elasticsearch.action" "RefreshAction" - "elasticsearch.request" "RefreshRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - } - - def "test elasticsearch get"() { - expect: - template.createIndex(indexName) - template.getClient().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - - when: - NativeSearchQuery query = new NativeSearchQueryBuilder() - .withIndices(indexName) - .withTypes(indexType) - .withIds([id]) - .build() - - then: - template.queryForIds(query) == [] - - when: - def result = template.index(IndexQueryBuilder.newInstance() - .withObject(new Doc()) - .withIndexName(indexName) - .withType(indexType) - .withId(id) - .build()) - template.refresh(Doc) - - then: - result == id - template.queryForList(query, Doc) == [new Doc()] - - and: - assertTraces(6) { - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - trace(2, 1) { - span(0) { - name "SearchAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "SearchAction" - "elasticsearch.action" "SearchAction" - "elasticsearch.request" "SearchRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.search.types" indexType - } - } - } - trace(3, 2) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.failed" 0 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.total" 2 - } - } - span(1) { - name "PutMappingAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(4, 1) { - span(0) { - name "RefreshAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "RefreshAction" - "elasticsearch.action" "RefreshAction" - "elasticsearch.request" "RefreshRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.shard.broadcast.failed" 0 - "elasticsearch.shard.broadcast.successful" 5 - "elasticsearch.shard.broadcast.total" 10 - } - } - } - trace(5, 1) { - span(0) { - name "SearchAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "SearchAction" - "elasticsearch.action" "SearchAction" - "elasticsearch.request" "SearchRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.search.types" indexType - } - } - } - } - - cleanup: - template.deleteIndex(indexName) - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } - - def "test results extractor"() { - setup: - template.createIndex(indexName) - testNode.client().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - - template.index(IndexQueryBuilder.newInstance() - .withObject(new Doc(id: 1, data: "doc a")) - .withIndexName(indexName) - .withId("a") - .build()) - template.index(IndexQueryBuilder.newInstance() - .withObject(new Doc(id: 2, data: "doc b")) - .withIndexName(indexName) - .withId("b") - .build()) - template.refresh(indexName) - TEST_WRITER.waitForTraces(5) - TEST_WRITER.clear() - - and: - def query = new NativeSearchQueryBuilder().withIndices(indexName).build() - def hits = new AtomicLong() - List> results = [] - def bucketTags = [:] - - when: - template.query(query, new ResultsExtractor() { - - @Override - Doc extract(SearchResponse response) { - hits.addAndGet(response.getHits().totalHits()) - results.addAll(response.hits.collect { it.source }) - if (response.getAggregations() != null) { - InternalNested internalNested = response.getAggregations().get("tag") - if (internalNested != null) { - Terms terms = internalNested.getAggregations().get("count_agg") - Collection buckets = terms.getBuckets() - for (Terms.Bucket bucket : buckets) { - bucketTags.put(Integer.valueOf(bucket.getKeyAsString()), bucket.getDocCount()) - } - } - } - return null - } - }) - - then: - hits.get() == 2 - results[0] == [id: "2", data: "doc b"] - results[1] == [id: "1", data: "doc a"] - bucketTags == [:] - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SearchAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "SearchAction" - "elasticsearch.action" "SearchAction" - "elasticsearch.request" "SearchRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - cleanup: - template.deleteIndex(indexName) - - where: - indexName = "test-index-extract" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/elasticsearch-transport-6.0.gradle b/instrumentation/elasticsearch/elasticsearch-transport-6.0/elasticsearch-transport-6.0.gradle deleted file mode 100644 index 6a68ca740e..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/elasticsearch-transport-6.0.gradle +++ /dev/null @@ -1,44 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.elasticsearch.client" - module = "transport" - versions = "[6.0.0,7.0.0)" - } - pass { - group = "org.elasticsearch" - module = "elasticsearch" - versions = "[6.0.0,7.0.0)" - } - fail { - group = "org.elasticsearch.client" - module = "transport" - versions = "[,6.0.0)" - } - fail { - group = "org.elasticsearch" - module = "elasticsearch" - versions = "[,6.0.0)" - } -} - -dependencies { - library group: 'org.elasticsearch.client', name: 'transport', version: '6.0.0' - - implementation project(':instrumentation:elasticsearch:elasticsearch-transport-common') - - // Ensure no cross interference - testImplementation project(':instrumentation:elasticsearch:elasticsearch-rest-5.0') - testImplementation project(':instrumentation:apache-httpasyncclient-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - - testLibrary group: 'org.elasticsearch.plugin', name: 'transport-netty4-client', version: '6.0.0' - - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0' - testImplementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0' - - // Limit tests to <6.5 as the latest versions have a breaking change for the tests. - latestDepTestLibrary group: 'org.elasticsearch.plugin', name: 'transport-netty4-client', version: '(6.1,6.5)' - latestDepTestLibrary group: 'org.elasticsearch.client', name: 'transport', version: '(6.1,6.5)' -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6NodeClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6NodeClientTest.groovy index fbb82ddb08..e02b30fe6a 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6NodeClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6NodeClientTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest import org.elasticsearch.common.io.FileSystemUtils import org.elasticsearch.common.settings.Settings diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6TransportClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6TransportClientTest.groovy index 3df070cde5..eaf33d9674 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6TransportClientTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-6.0/javaagent/src/test/groovy/Elasticsearch6TransportClientTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest import org.elasticsearch.client.transport.TransportClient import org.elasticsearch.common.io.FileSystemUtils diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentationModule.java deleted file mode 100644 index 7018dd0f23..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/Elasticsearch6TransportClientInstrumentationModule.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v6_0; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.elasticsearch.action.Action; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; - -/** - * Most of this class is identical to version 5's instrumentation, but they changed an interface to - * an abstract class, so the bytecode isn't directly compatible. - */ -@AutoService(InstrumentationModule.class) -public class Elasticsearch6TransportClientInstrumentationModule extends InstrumentationModule { - public Elasticsearch6TransportClientInstrumentationModule() { - super("elasticsearch-transport", "elasticsearch-transport-6.0", "elasticsearch"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AbstractClientInstrumentation()); - } - - public static class AbstractClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - // If we want to be more generic, we could instrument the interface instead: - // .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient")))) - return named("org.elasticsearch.client.support.AbstractClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArgument(0, named("org.elasticsearch.action.Action"))) - .and(takesArgument(1, named("org.elasticsearch.action.ActionRequest"))) - .and(takesArgument(2, named("org.elasticsearch.action.ActionListener"))), - Elasticsearch6TransportClientInstrumentationModule.class.getName() - + "$Elasticsearch6TransportClientAdvice"); - } - } - - public static class Elasticsearch6TransportClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Action action, - @Advice.Argument(1) ActionRequest actionRequest, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Argument(value = 2, readOnly = false) - ActionListener actionListener) { - - span = tracer().startSpan(null, action); - scope = tracer().startScope(span); - tracer().onRequest(span, action.getClass(), actionRequest.getClass()); - actionListener = new TransportActionListener<>(actionRequest, actionListener, span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/TransportActionListener.java b/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/TransportActionListener.java deleted file mode 100644 index 3c87f52341..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v6_0/TransportActionListener.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.v6_0; - -import static io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.ElasticsearchTransportClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ActionRequest; -import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.action.DocWriteRequest; -import org.elasticsearch.action.IndicesRequest; -import org.elasticsearch.action.bulk.BulkShardResponse; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.support.broadcast.BroadcastResponse; -import org.elasticsearch.action.support.nodes.BaseNodesResponse; -import org.elasticsearch.action.support.replication.ReplicationResponse; - -/** - * Most of this class is identical to version 5's instrumentation, but they changed an interface to - * an abstract class, so the bytecode isn't directly compatible. - */ -public class TransportActionListener implements ActionListener { - - private final ActionListener listener; - private final Span span; - - public TransportActionListener( - ActionRequest actionRequest, ActionListener listener, Span span) { - this.listener = listener; - this.span = span; - onRequest(actionRequest); - } - - private void onRequest(ActionRequest request) { - if (request instanceof IndicesRequest) { - IndicesRequest req = (IndicesRequest) request; - String[] indices = req.indices(); - if (indices != null && indices.length > 0) { - span.setAttribute("elasticsearch.request.indices", String.join(",", indices)); - } - } - if (request instanceof SearchRequest) { - SearchRequest req = (SearchRequest) request; - String[] types = req.types(); - if (types != null && types.length > 0) { - span.setAttribute("elasticsearch.request.search.types", String.join(",", types)); - } - } - if (request instanceof DocWriteRequest) { - DocWriteRequest req = (DocWriteRequest) request; - span.setAttribute("elasticsearch.request.write.type", req.type()); - span.setAttribute("elasticsearch.request.write.routing", req.routing()); - span.setAttribute("elasticsearch.request.write.version", req.version()); - } - } - - @Override - public void onResponse(T response) { - if (response.remoteAddress() != null) { - NetPeerUtils.setNetPeer( - span, - response.remoteAddress().address().getHostName(), - response.remoteAddress().getAddress()); - span.setAttribute( - SemanticAttributes.NET_PEER_PORT, (long) response.remoteAddress().getPort()); - } - - if (response instanceof GetResponse) { - GetResponse resp = (GetResponse) response; - span.setAttribute("elasticsearch.type", resp.getType()); - span.setAttribute("elasticsearch.id", resp.getId()); - span.setAttribute("elasticsearch.version", resp.getVersion()); - } - - if (response instanceof BroadcastResponse) { - BroadcastResponse resp = (BroadcastResponse) response; - span.setAttribute("elasticsearch.shard.broadcast.total", resp.getTotalShards()); - span.setAttribute("elasticsearch.shard.broadcast.successful", resp.getSuccessfulShards()); - span.setAttribute("elasticsearch.shard.broadcast.failed", resp.getFailedShards()); - } - - if (response instanceof ReplicationResponse) { - ReplicationResponse resp = (ReplicationResponse) response; - span.setAttribute("elasticsearch.shard.replication.total", resp.getShardInfo().getTotal()); - span.setAttribute( - "elasticsearch.shard.replication.successful", resp.getShardInfo().getSuccessful()); - span.setAttribute("elasticsearch.shard.replication.failed", resp.getShardInfo().getFailed()); - } - - if (response instanceof IndexResponse) { - span.setAttribute( - "elasticsearch.response.status", ((IndexResponse) response).status().getStatus()); - } - - if (response instanceof BulkShardResponse) { - BulkShardResponse resp = (BulkShardResponse) response; - span.setAttribute("elasticsearch.shard.bulk.id", resp.getShardId().getId()); - span.setAttribute("elasticsearch.shard.bulk.index", resp.getShardId().getIndexName()); - } - - if (response instanceof BaseNodesResponse) { - BaseNodesResponse resp = (BaseNodesResponse) response; - if (resp.hasFailures()) { - span.setAttribute("elasticsearch.node.failures", resp.failures().size()); - } - span.setAttribute("elasticsearch.node.cluster.name", resp.getClusterName().value()); - } - - tracer().end(span); - listener.onResponse(response); - } - - @Override - public void onFailure(Exception e) { - tracer().endExceptionally(span, e); - listener.onFailure(e); - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/test/groovy/Elasticsearch6NodeClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/test/groovy/Elasticsearch6NodeClientTest.groovy deleted file mode 100644 index e02b30fe6a..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/test/groovy/Elasticsearch6NodeClientTest.groovy +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty4Plugin -import spock.lang.Shared - -class Elasticsearch6NodeClientTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - def client = testNode.client() - - def setupSpec() { - - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(InternalSettingsPreparer.prepareEnvironment(settings, null), [Netty4Plugin]) - testNode.start() - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - testNode.client().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - def result = client.admin().cluster().health(new ClusterHealthRequest()).get() - - def status = result.status - - expect: - status.name() == "GREEN" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - } - } - - def "test elasticsearch error"() { - when: - client.prepareGet(indexName, indexType, id).get() - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GetAction" - kind CLIENT - errored true - errorEvent IndexNotFoundException, "no such index" - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - indexType = "test-type" - id = "1" - } - - def "test elasticsearch get"() { - setup: - assert TEST_WRITER.traces == [] - def indexResult = client.admin().indices().prepareCreate(indexName).get() - TEST_WRITER.waitForTraces(1) - - expect: - indexResult.index() == indexName - TEST_WRITER.traces.size() == 1 - - when: - def emptyResult = client.prepareGet(indexName, indexType, id).get() - - then: - !emptyResult.isExists() - emptyResult.id == id - emptyResult.type == indexType - emptyResult.index == indexName - - when: - def createResult = client.prepareIndex(indexName, indexType, id).setSource([:]).get() - - then: - createResult.id == id - createResult.type == indexType - createResult.index == indexName - createResult.status().status == 201 - - when: - def result = client.prepareGet(indexName, indexType, id).get() - - then: - result.isExists() - result.id == id - result.type == indexType - result.index == indexName - - and: - assertTraces(4) { - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version"(-1) - } - } - } - trace(2, 2) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.total" 2 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.failed" 0 - } - } - span(1) { - name "PutMappingAction" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(3, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version" 1 - } - } - } - } - - cleanup: - client.admin().indices().prepareDelete(indexName).get() - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/test/groovy/Elasticsearch6TransportClientTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/test/groovy/Elasticsearch6TransportClientTest.groovy deleted file mode 100644 index eaf33d9674..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-6.0/src/test/groovy/Elasticsearch6TransportClientTest.groovy +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest -import org.elasticsearch.client.transport.TransportClient -import org.elasticsearch.common.io.FileSystemUtils -import org.elasticsearch.common.settings.Settings -import org.elasticsearch.common.transport.TransportAddress -import org.elasticsearch.index.IndexNotFoundException -import org.elasticsearch.node.InternalSettingsPreparer -import org.elasticsearch.node.Node -import org.elasticsearch.transport.Netty4Plugin -import org.elasticsearch.transport.RemoteTransportException -import org.elasticsearch.transport.TransportService -import org.elasticsearch.transport.client.PreBuiltTransportClient -import spock.lang.Shared - -class Elasticsearch6TransportClientTest extends AgentTestRunner { - public static final long TIMEOUT = 10000 // 10 seconds - - @Shared - TransportAddress tcpPublishAddress - @Shared - Node testNode - @Shared - File esWorkingDir - @Shared - String clusterName = UUID.randomUUID().toString() - - @Shared - TransportClient client - - def setupSpec() { - esWorkingDir = File.createTempDir("test-es-working-dir-", "") - esWorkingDir.deleteOnExit() - println "ES work dir: $esWorkingDir" - - def settings = Settings.builder() - .put("path.home", esWorkingDir.path) - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - testNode = new Node(InternalSettingsPreparer.prepareEnvironment(settings, null), [Netty4Plugin]) - testNode.start() - tcpPublishAddress = testNode.injector().getInstance(TransportService).boundAddress().publishAddress() - - client = new PreBuiltTransportClient( - Settings.builder() - // Since we use listeners to close spans this should make our span closing deterministic which is good for tests - .put("thread_pool.listener.size", 1) - .put(CLUSTER_NAME_SETTING.getKey(), clusterName) - .build() - ) - client.addTransportAddress(tcpPublishAddress) - runUnderTrace("setup") { - // this may potentially create multiple requests and therefore multiple spans, so we wrap this call - // into a top level trace to get exactly one trace in the result. - client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet(TIMEOUT) - } - TEST_WRITER.waitForTraces(1) - } - - def cleanupSpec() { - testNode?.close() - if (esWorkingDir != null) { - FileSystemUtils.deleteSubDirectories(esWorkingDir.toPath()) - esWorkingDir.delete() - } - } - - def "test elasticsearch status"() { - setup: - def result = client.admin().cluster().health(new ClusterHealthRequest()) - - def status = result.get().status - - expect: - status.name() == "GREEN" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ClusterHealthAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "ClusterHealthAction" - "elasticsearch.action" "ClusterHealthAction" - "elasticsearch.request" "ClusterHealthRequest" - } - } - } - } - } - - def "test elasticsearch error"() { - when: - client.prepareGet(indexName, indexType, id).get() - - then: - thrown IndexNotFoundException - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GetAction" - kind CLIENT - errored true - errorEvent RemoteTransportException, String - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - } - } - } - } - - where: - indexName = "invalid-index" - indexType = "test-type" - id = "1" - } - - def "test elasticsearch get"() { - setup: - assert TEST_WRITER.traces == [] - def indexResult = client.admin().indices().prepareCreate(indexName).get() - TEST_WRITER.waitForTraces(1) - - expect: - indexResult.index() == indexName - TEST_WRITER.traces.size() == 1 - - when: - def emptyResult = client.prepareGet(indexName, indexType, id).get() - - then: - !emptyResult.isExists() - emptyResult.id == id - emptyResult.type == indexType - emptyResult.index == indexName - - when: - def createResult = client.prepareIndex(indexName, indexType, id).setSource([:]).get() - - then: - createResult.id == id - createResult.type == indexType - createResult.index == indexName - createResult.status().status == 201 - - when: - def result = client.prepareGet(indexName, indexType, id).get() - - then: - result.isExists() - result.id == id - result.type == indexType - result.index == indexName - - and: - assertTraces(5) { - sortTraces { - // IndexAction and PutMappingAction run in separate threads and so their order is not always the same - if (traces[2][0].name == "IndexAction") { - def tmp = traces[2] - traces[2] = traces[3] - traces[3] = tmp - } - } - trace(0, 1) { - span(0) { - name "CreateIndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "CreateIndexAction" - "elasticsearch.action" "CreateIndexAction" - "elasticsearch.request" "CreateIndexRequest" - "elasticsearch.request.indices" indexName - } - } - } - trace(1, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version"(-1) - } - } - } - trace(2, 1) { - span(0) { - name "PutMappingAction" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "PutMappingAction" - "elasticsearch.action" "PutMappingAction" - "elasticsearch.request" "PutMappingRequest" - } - } - } - trace(3, 1) { - span(0) { - name "IndexAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "IndexAction" - "elasticsearch.action" "IndexAction" - "elasticsearch.request" "IndexRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.request.write.type" indexType - "elasticsearch.request.write.version"(-3) - "elasticsearch.response.status" 201 - "elasticsearch.shard.replication.total" 2 - "elasticsearch.shard.replication.successful" 1 - "elasticsearch.shard.replication.failed" 0 - } - } - } - trace(4, 1) { - span(0) { - name "GetAction" - kind CLIENT - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_IP.key()}" tcpPublishAddress.address - "${SemanticAttributes.NET_PEER_PORT.key()}" tcpPublishAddress.port - "${SemanticAttributes.DB_SYSTEM.key()}" "elasticsearch" - "${SemanticAttributes.DB_OPERATION.key()}" "GetAction" - "elasticsearch.action" "GetAction" - "elasticsearch.request" "GetRequest" - "elasticsearch.request.indices" indexName - "elasticsearch.type" indexType - "elasticsearch.id" "1" - "elasticsearch.version" 1 - } - } - } - } - - cleanup: - client.admin().indices().prepareDelete(indexName).get() - - where: - indexName = "test-index" - indexType = "test-type" - id = "1" - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common/elasticsearch-transport-common.gradle b/instrumentation/elasticsearch/elasticsearch-transport-common/elasticsearch-transport-common.gradle deleted file mode 100644 index c4367baf67..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-common/elasticsearch-transport-common.gradle +++ /dev/null @@ -1,5 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - compileOnly group: 'org.elasticsearch', name: 'elasticsearch', version: '2.0.0' -} diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportClientTracer.java b/instrumentation/elasticsearch/elasticsearch-transport-common/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportClientTracer.java deleted file mode 100644 index 7aac655d17..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-transport-common/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportClientTracer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import java.net.InetSocketAddress; -import org.elasticsearch.action.Action; - -public class ElasticsearchTransportClientTracer - extends DatabaseClientTracer> { - private static final ElasticsearchTransportClientTracer TRACER = - new ElasticsearchTransportClientTracer(); - - public static ElasticsearchTransportClientTracer tracer() { - return TRACER; - } - - public Span onRequest(Span span, Class action, Class request) { - span.setAttribute("elasticsearch.action", action.getSimpleName()); - span.setAttribute("elasticsearch.request", request.getSimpleName()); - return span; - } - - @Override - protected String normalizeQuery(Action query) { - return query.getClass().getSimpleName(); - } - - @Override - protected String dbSystem(Void connection) { - return "elasticsearch"; - } - - @Override - protected InetSocketAddress peerAddress(Void connection) { - return null; - } - - @Override - protected void onStatement(Span span, String statement) { - span.setAttribute(SemanticAttributes.DB_OPERATION, statement); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.elasticsearch"; - } -} diff --git a/instrumentation/executors/executors.gradle b/instrumentation/executors/executors.gradle deleted file mode 100644 index 4eef92f4d9..0000000000 --- a/instrumentation/executors/executors.gradle +++ /dev/null @@ -1,7 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk() - } -} diff --git a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/AbstractExecutorInstrumentation.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/AbstractExecutorInstrumentation.java deleted file mode 100644 index f60b34344a..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/AbstractExecutorInstrumentation.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.any; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Executor; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractExecutorInstrumentation implements TypeInstrumentation { - private static final Logger log = LoggerFactory.getLogger(AbstractExecutorInstrumentation.class); - - private static final String EXECUTORS_INCLUDE_PROPERTY_NAME = - "otel.instrumentation.executors.include"; - - private static final String EXECUTORS_INCLUDE_ALL_PROPERTY_NAME = - "otel.instrumentation.executors.include-all"; - - // hopefully these configuration properties can be static after - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1345 - private final boolean includeAll = - Config.get().getBooleanProperty(EXECUTORS_INCLUDE_ALL_PROPERTY_NAME, false); - - /** - * Only apply executor instrumentation to allowed executors. To apply to all executors, use - * override setting above. - */ - private final Collection includeExecutors; - - /** - * Some frameworks have their executors defined as anon classes inside other classes. Referencing - * anon classes by name would be fragile, so instead we will use list of class prefix names. Since - * checking this list is more expensive (O(n)) we should try to keep it short. - */ - private final Collection includePrefixes; - - protected AbstractExecutorInstrumentation() { - if (includeAll) { - includeExecutors = Collections.emptyList(); - includePrefixes = Collections.emptyList(); - } else { - String[] includeExecutors = { - "akka.actor.ActorSystemImpl$$anon$1", - "akka.dispatch.BalancingDispatcher", - "akka.dispatch.Dispatcher", - "akka.dispatch.Dispatcher$LazyExecutorServiceDelegate", - "akka.dispatch.ExecutionContexts$sameThreadExecutionContext$", - "akka.dispatch.forkjoin.ForkJoinPool", - "akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinPool", - "akka.dispatch.MessageDispatcher", - "akka.dispatch.PinnedDispatcher", - "com.google.common.util.concurrent.AbstractListeningExecutorService", - "com.google.common.util.concurrent.MoreExecutors$ListeningDecorator", - "com.google.common.util.concurrent.MoreExecutors$ScheduledListeningDecorator", - "io.netty.channel.epoll.EpollEventLoop", - "io.netty.channel.epoll.EpollEventLoopGroup", - "io.netty.channel.MultithreadEventLoopGroup", - "io.netty.channel.nio.NioEventLoop", - "io.netty.channel.nio.NioEventLoopGroup", - "io.netty.channel.SingleThreadEventLoop", - "io.netty.util.concurrent.AbstractEventExecutor", - "io.netty.util.concurrent.AbstractEventExecutorGroup", - "io.netty.util.concurrent.AbstractScheduledEventExecutor", - "io.netty.util.concurrent.DefaultEventExecutor", - "io.netty.util.concurrent.DefaultEventExecutorGroup", - "io.netty.util.concurrent.GlobalEventExecutor", - "io.netty.util.concurrent.MultithreadEventExecutorGroup", - "io.netty.util.concurrent.SingleThreadEventExecutor", - "java.util.concurrent.AbstractExecutorService", - "java.util.concurrent.CompletableFuture$ThreadPerTaskExecutor", - "java.util.concurrent.Executors$DelegatedExecutorService", - "java.util.concurrent.Executors$FinalizableDelegatedExecutorService", - "java.util.concurrent.ForkJoinPool", - "java.util.concurrent.ScheduledThreadPoolExecutor", - "java.util.concurrent.ThreadPoolExecutor", - "org.eclipse.jetty.util.thread.QueuedThreadPool", - "org.eclipse.jetty.util.thread.ReservedThreadExecutor", - "org.glassfish.grizzly.threadpool.GrizzlyExecutorService", - "play.api.libs.streams.Execution$trampoline$", - "scala.concurrent.forkjoin.ForkJoinPool", - "scala.concurrent.Future$InternalCallbackExecutor$", - "scala.concurrent.impl.ExecutionContextImpl", - }; - Set combined = new HashSet<>(Arrays.asList(includeExecutors)); - combined.addAll(Config.get().getListProperty(EXECUTORS_INCLUDE_PROPERTY_NAME)); - this.includeExecutors = Collections.unmodifiableSet(combined); - - String[] includePrefixes = {"slick.util.AsyncExecutor$"}; - this.includePrefixes = Collections.unmodifiableCollection(Arrays.asList(includePrefixes)); - } - } - - @Override - public ElementMatcher typeMatcher() { - ElementMatcher.Junction matcher = any(); - final ElementMatcher.Junction hasExecutorInterfaceMatcher = - implementsInterface(named(Executor.class.getName())); - if (!includeAll) { - matcher = - matcher.and( - new ElementMatcher() { - @Override - public boolean matches(TypeDescription target) { - boolean allowed = includeExecutors.contains(target.getName()); - - // Check for possible prefixes match only if not allowed already - if (!allowed) { - for (String name : includePrefixes) { - if (target.getName().startsWith(name)) { - allowed = true; - break; - } - } - } - - if (!allowed - && log.isDebugEnabled() - && hasExecutorInterfaceMatcher.matches(target)) { - log.debug("Skipping executor instrumentation for {}", target.getName()); - } - return allowed; - } - }); - } - return matcher.and(hasExecutorInterfaceMatcher); // Apply expensive matcher last. - } -} diff --git a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/CallableInstrumentation.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/CallableInstrumentation.java deleted file mode 100644 index 15113e7abd..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/CallableInstrumentation.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import java.util.concurrent.Callable; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class CallableInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named(Callable.class.getName())); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("call").and(takesArguments(0)).and(isPublic()), - CallableInstrumentation.class.getName() + "$CallableAdvice"); - } - - public static class CallableAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope enter(@Advice.This Callable thiz) { - ContextStore contextStore = - InstrumentationContext.get(Callable.class, State.class); - return AdviceUtils.startTaskScope(contextStore, thiz); - } - - @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/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java deleted file mode 100644 index fa18c0b560..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.Future; - -@AutoService(InstrumentationModule.class) -public class ExecutorInstrumentationModule extends InstrumentationModule { - public ExecutorInstrumentationModule() { - super("executor"); - } - - @Override - public List typeInstrumentations() { - return asList( - new CallableInstrumentation(), - new FutureInstrumentation(), - new JavaExecutorInstrumentation(), - new JavaForkJoinTaskInstrumentation(), - new RunnableInstrumentation()); - } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put(Callable.class.getName(), State.class.getName()); - map.put(ForkJoinTask.class.getName(), State.class.getName()); - map.put(Future.class.getName(), State.class.getName()); - map.put(Runnable.class.getName(), State.class.getName()); - return Collections.unmodifiableMap(map); - } -} diff --git a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/FutureInstrumentation.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/FutureInstrumentation.java deleted file mode 100644 index 75e2074e0d..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/FutureInstrumentation.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.concurrent.Future; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class FutureInstrumentation implements TypeInstrumentation { - private static final Logger log = LoggerFactory.getLogger(FutureInstrumentation.class); - - /** - * Only apply executor instrumentation to allowed executors. In the future, this restriction may - * be lifted to include all executors. - */ - private static final Collection ALLOWED_FUTURES; - - static { - String[] allowed = { - "akka.dispatch.forkjoin.ForkJoinTask", - "akka.dispatch.forkjoin.ForkJoinTask$AdaptedCallable", - "akka.dispatch.forkjoin.ForkJoinTask$AdaptedRunnable", - "akka.dispatch.forkjoin.ForkJoinTask$AdaptedRunnableAction", - "akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask", - "akka.dispatch.Mailbox", - "com.google.common.util.concurrent.AbstractFuture", - "com.google.common.util.concurrent.AbstractFuture$TrustedFuture", - "com.google.common.util.concurrent.ListenableFutureTask", - "com.google.common.util.concurrent.SettableFuture", - "io.netty.util.concurrent.CompleteFuture", - "io.netty.util.concurrent.FailedFuture", - "io.netty.util.concurrent.ScheduledFutureTask", - "java.util.concurrent.CompletableFuture$BiApply", - "java.util.concurrent.CompletableFuture$BiCompletion", - "java.util.concurrent.CompletableFuture$BiRelay", - "java.util.concurrent.CompletableFuture$ThreadPerTaskExecutor", - "java.util.concurrent.CountedCompleter", - "java.util.concurrent.ExecutorCompletionService$QueueingFuture", - "java.util.concurrent.ForkJoinTask", - "java.util.concurrent.ForkJoinTask$AdaptedCallable", - "java.util.concurrent.ForkJoinTask$RunnableExecuteAction", - "java.util.concurrent.FutureTask", - "java.util.concurrent.RecursiveAction", - "java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask", - "scala.collection.parallel.AdaptiveWorkStealingForkJoinTasks$WrappedTask", - "scala.concurrent.forkjoin.ForkJoinTask", - "scala.concurrent.forkjoin.ForkJoinTask$AdaptedCallable", - "scala.concurrent.forkjoin.ForkJoinTask$AdaptedRunnable", - "scala.concurrent.forkjoin.ForkJoinTask$AdaptedRunnableAction", - "scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask", - }; - ALLOWED_FUTURES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowed))); - } - - @Override - public ElementMatcher typeMatcher() { - final ElementMatcher.Junction hasFutureInterfaceMatcher = - implementsInterface(named(Future.class.getName())); - return new ElementMatcher.Junction.AbstractBase() { - @Override - public boolean matches(TypeDescription target) { - boolean allowed = ALLOWED_FUTURES.contains(target.getName()); - if (!allowed && log.isDebugEnabled() && hasFutureInterfaceMatcher.matches(target)) { - log.debug("Skipping future instrumentation for {}", target.getName()); - } - return allowed; - } - }.and(hasFutureInterfaceMatcher); // Apply expensive matcher last. - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("cancel").and(returns(boolean.class)), - FutureInstrumentation.class.getName() + "$CanceledFutureAdvice"); - } - - public static class CanceledFutureAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void exit(@Advice.This Future future) { - // Try to clear parent span even if future was not cancelled: - // the expectation is that parent span should be cleared after 'cancel' - // is called, one way or another - ContextStore contextStore = - InstrumentationContext.get(Future.class, State.class); - State state = contextStore.get(future); - if (state != null) { - state.clearParentContext(); - } - } - } -} diff --git a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/JavaExecutorInstrumentation.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/JavaExecutorInstrumentation.java deleted file mode 100644 index 8b3cba5c41..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/JavaExecutorInstrumentation.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static net.bytebuddy.matcher.ElementMatchers.nameMatches; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.CallableWrapper; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.Future; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JavaExecutorInstrumentation extends AbstractExecutorInstrumentation { - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("execute").and(takesArgument(0, Runnable.class)).and(takesArguments(1)), - JavaExecutorInstrumentation.class.getName() + "$SetExecuteRunnableStateAdvice"); - // Netty uses addTask as the acutal core of their submission; there are non-standard variations - // like execute(Runnable,boolean) that aren't caught by standard instrumentation - transformers.put( - named("addTask").and(takesArgument(0, Runnable.class)).and(takesArguments(1)), - JavaExecutorInstrumentation.class.getName() + "$SetExecuteRunnableStateAdvice"); - transformers.put( - named("execute").and(takesArgument(0, ForkJoinTask.class)), - JavaExecutorInstrumentation.class.getName() + "$SetJavaForkJoinStateAdvice"); - transformers.put( - named("submit").and(takesArgument(0, Runnable.class)), - JavaExecutorInstrumentation.class.getName() + "$SetSubmitRunnableStateAdvice"); - transformers.put( - named("submit").and(takesArgument(0, Callable.class)), - JavaExecutorInstrumentation.class.getName() + "$SetCallableStateAdvice"); - transformers.put( - named("submit").and(takesArgument(0, ForkJoinTask.class)), - JavaExecutorInstrumentation.class.getName() + "$SetJavaForkJoinStateAdvice"); - transformers.put( - nameMatches("invoke(Any|All)$").and(takesArgument(0, Collection.class)), - JavaExecutorInstrumentation.class.getName() - + "$SetCallableStateForCallableCollectionAdvice"); - transformers.put( - nameMatches("invoke").and(takesArgument(0, ForkJoinTask.class)), - JavaExecutorInstrumentation.class.getName() + "$SetJavaForkJoinStateAdvice"); - transformers.put( - named("schedule").and(takesArgument(0, Runnable.class)), - JavaExecutorInstrumentation.class.getName() + "$SetSubmitRunnableStateAdvice"); - transformers.put( - named("schedule").and(takesArgument(0, Callable.class)), - JavaExecutorInstrumentation.class.getName() + "$SetCallableStateAdvice"); - return transformers; - } - - public static class SetExecuteRunnableStateAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static State enterJobSubmit( - @Advice.Argument(value = 0, readOnly = false) Runnable task) { - Runnable newTask = RunnableWrapper.wrapIfNeeded(task); - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask)) { - task = newTask; - ContextStore contextStore = - InstrumentationContext.get(Runnable.class, State.class); - return ExecutorInstrumentationUtils.setupState( - contextStore, newTask, Java8BytecodeBridge.currentContext()); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void exitJobSubmit( - @Advice.Enter State state, @Advice.Thrown Throwable throwable) { - ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); - } - } - - public static class SetJavaForkJoinStateAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static State enterJobSubmit( - @Advice.Argument(value = 0, readOnly = false) ForkJoinTask task) { - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(task)) { - ContextStore contextStore = - InstrumentationContext.get(ForkJoinTask.class, State.class); - return ExecutorInstrumentationUtils.setupState( - contextStore, task, Java8BytecodeBridge.currentContext()); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void exitJobSubmit( - @Advice.Enter State state, @Advice.Thrown Throwable throwable) { - ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); - } - } - - public static class SetSubmitRunnableStateAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static State enterJobSubmit( - @Advice.Argument(value = 0, readOnly = false) Runnable task) { - Runnable newTask = RunnableWrapper.wrapIfNeeded(task); - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask)) { - task = newTask; - ContextStore contextStore = - InstrumentationContext.get(Runnable.class, State.class); - return ExecutorInstrumentationUtils.setupState( - contextStore, newTask, Java8BytecodeBridge.currentContext()); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void exitJobSubmit( - @Advice.Enter State state, - @Advice.Thrown Throwable throwable, - @Advice.Return Future future) { - if (state != null && future != null) { - ContextStore contextStore = - InstrumentationContext.get(Future.class, State.class); - contextStore.put(future, state); - } - ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); - } - } - - public static class SetCallableStateAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static State enterJobSubmit( - @Advice.Argument(value = 0, readOnly = false) Callable task) { - Callable newTask = CallableWrapper.wrapIfNeeded(task); - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask)) { - task = newTask; - ContextStore contextStore = - InstrumentationContext.get(Callable.class, State.class); - return ExecutorInstrumentationUtils.setupState( - contextStore, newTask, Java8BytecodeBridge.currentContext()); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void exitJobSubmit( - @Advice.Enter State state, - @Advice.Thrown Throwable throwable, - @Advice.Return Future future) { - if (state != null && future != null) { - ContextStore contextStore = - InstrumentationContext.get(Future.class, State.class); - contextStore.put(future, state); - } - ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); - } - } - - public static class SetCallableStateForCallableCollectionAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Collection submitEnter( - @Advice.Argument(value = 0, readOnly = false) Collection> tasks) { - if (tasks != null) { - Collection> wrappedTasks = new ArrayList<>(tasks.size()); - for (Callable task : tasks) { - if (task != null) { - Callable newTask = CallableWrapper.wrapIfNeeded(task); - wrappedTasks.add(newTask); - ContextStore contextStore = - InstrumentationContext.get(Callable.class, State.class); - ExecutorInstrumentationUtils.setupState( - contextStore, newTask, Java8BytecodeBridge.currentContext()); - } - } - tasks = wrappedTasks; - return tasks; - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void submitExit( - @Advice.Enter Collection> wrappedTasks, - @Advice.Thrown Throwable throwable) { - /* - Note1: invokeAny doesn't return any futures so all we need to do for it - is to make sure we close all scopes in case of an exception. - Note2: invokeAll does return futures - but according to its documentation - it actually only returns after all futures have been completed - i.e. it blocks. - This means we do not need to setup any hooks on these futures, we just need to clean - up any continuations in case of an error. - (according to ExecutorService docs and AbstractExecutorService code) - */ - if (null != throwable && wrappedTasks != null) { - for (Callable task : wrappedTasks) { - if (task != null) { - ContextStore contextStore = - InstrumentationContext.get(Callable.class, State.class); - State state = contextStore.get(task); - if (state != null) { - /* - Note: this may potentially close somebody else's continuation if we didn't set it - up in setupState because it was already present before us. This should be safe but - may lead to non-attributed async work in some very rare cases. - Alternative is to not close continuation here if we did not set it up in setupState - but this may potentially lead to memory leaks if callers do not properly handle - exceptions. - */ - state.clearParentContext(); - } - } - } - } - } - } -} diff --git a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/JavaForkJoinTaskInstrumentation.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/JavaForkJoinTaskInstrumentation.java deleted file mode 100644 index 29588311fa..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/JavaForkJoinTaskInstrumentation.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * Instrument {@link ForkJoinTask}. - * - *

Note: There are quite a few separate implementations of {@code ForkJoinTask}/{@code - * ForkJoinPool}: JVM, Akka, Scala, Netty to name a few. This class handles JVM version. - */ -public class JavaForkJoinTaskInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named(ForkJoinTask.class.getName())); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("exec").and(takesArguments(0)).and(not(isAbstract())), - JavaForkJoinTaskInstrumentation.class.getName() + "$ForkJoinTaskAdvice"); - } - - public static class ForkJoinTaskAdvice { - - /** - * When {@link ForkJoinTask} object is submitted to {@link ForkJoinPool} as {@link Runnable} or - * {@link Callable} it will not get wrapped, instead it will be casted to {@code ForkJoinTask} - * directly. This means state is still stored in {@code Runnable} or {@code Callable} and we - * need to use that state. - */ - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope enter(@Advice.This ForkJoinTask thiz) { - ContextStore contextStore = - InstrumentationContext.get(ForkJoinTask.class, State.class); - Scope scope = AdviceUtils.startTaskScope(contextStore, thiz); - if (thiz instanceof Runnable) { - ContextStore runnableContextStore = - InstrumentationContext.get(Runnable.class, State.class); - Scope newScope = AdviceUtils.startTaskScope(runnableContextStore, (Runnable) thiz); - if (null != newScope) { - if (null != scope) { - newScope.close(); - } else { - scope = newScope; - } - } - } - if (thiz instanceof Callable) { - ContextStore callableContextStore = - InstrumentationContext.get(Callable.class, State.class); - Scope newScope = AdviceUtils.startTaskScope(callableContextStore, (Callable) thiz); - if (null != newScope) { - if (null != scope) { - newScope.close(); - } else { - scope = newScope; - } - } - } - return scope; - } - - @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/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/NonStandardExecutorInstrumentationModule.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/NonStandardExecutorInstrumentationModule.java deleted file mode 100644 index 8acd38500f..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/NonStandardExecutorInstrumentationModule.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class NonStandardExecutorInstrumentationModule extends InstrumentationModule { - - public NonStandardExecutorInstrumentationModule() { - super("executor", "non-standard-executor"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new OtherExecutorsInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap(Runnable.class.getName(), State.class.getName()); - } - - public static class OtherExecutorsInstrumentation extends AbstractExecutorInstrumentation { - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - - transformers.put( - // org.eclipse.jetty.util.thread.QueuedThreadPool - named("dispatch").and(takesArguments(1)).and(takesArgument(0, Runnable.class)), - JavaExecutorInstrumentation.class.getName() + "$SetExecuteRunnableStateAdvice"); - return transformers; - } - } -} diff --git a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/RunnableInstrumentation.java b/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/RunnableInstrumentation.java deleted file mode 100644 index 38a0d2652a..0000000000 --- a/instrumentation/executors/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/RunnableInstrumentation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.javaconcurrent; - -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.AdviceUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class RunnableInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named(Runnable.class.getName())); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("run").and(takesArguments(0)).and(isPublic()), - RunnableInstrumentation.class.getName() + "$RunnableAdvice"); - } - - public static class RunnableAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static Scope enter(@Advice.This Runnable thiz) { - ContextStore contextStore = - InstrumentationContext.get(Runnable.class, State.class); - return AdviceUtils.startTaskScope(contextStore, thiz); - } - - @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/executors/src/test/groovy/CompletableFutureTest.groovy b/instrumentation/executors/src/test/groovy/CompletableFutureTest.groovy deleted file mode 100644 index 593fe718ca..0000000000 --- a/instrumentation/executors/src/test/groovy/CompletableFutureTest.groovy +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.concurrent.ArrayBlockingQueue -import java.util.concurrent.CompletableFuture -import java.util.concurrent.ThreadPoolExecutor -import java.util.concurrent.TimeUnit -import java.util.function.Function -import java.util.function.Supplier -import spock.lang.Requires - -@Requires({ javaVersion >= 1.8 }) -class CompletableFutureTest extends AgentTestRunner { - - def "CompletableFuture test"() { - setup: - def pool = new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - def differentPool = new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - def supplier = new Supplier() { - @Override - String get() { - getTestTracer().spanBuilder("supplier").startSpan().end() - sleep(1000) - return "a" - } - } - - def function = new Function() { - @Override - String apply(String s) { - getTestTracer().spanBuilder("function").startSpan().end() - return s + "c" - } - } - - def result = new Supplier() { - @Override - String get() { - runUnderTrace("parent") { - return CompletableFuture.supplyAsync(supplier, pool) - .thenCompose({ s -> CompletableFuture.supplyAsync(new AppendingSupplier(s), differentPool) }) - .thenApply(function) - .get() - } - } - }.get() - - TEST_WRITER.waitForTraces(1) - List trace = TEST_WRITER.traces[0] - - expect: - result == "abc" - - TEST_WRITER.traces.size() == 1 - trace.size() == 4 - trace.get(0).name == "parent" - trace.get(1).name == "supplier" - trace.get(1).parentSpanId == trace.get(0).spanId - trace.get(2).name == "appendingSupplier" - trace.get(2).parentSpanId == trace.get(0).spanId - trace.get(3).name == "function" - trace.get(3).parentSpanId == trace.get(0).spanId - - cleanup: - pool?.shutdown() - differentPool?.shutdown() - } - - def "test supplyAsync"() { - when: - CompletableFuture completableFuture = runUnderTrace("parent") { - def result = CompletableFuture.supplyAsync { - runUnderTrace("child") { - "done" - } - } - return result - } - - then: - completableFuture.get() == "done" - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "child", span(0)) - } - } - } - - def "test thenApply"() { - when: - CompletableFuture completableFuture = runUnderTrace("parent") { - CompletableFuture.supplyAsync { - "done" - }.thenApply { result -> - runUnderTrace("child") { - result - } - } - } - - then: - completableFuture.get() == "done" - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "child", span(0)) - } - } - } - - def "test thenApplyAsync"() { - when: - CompletableFuture completableFuture = runUnderTrace("parent") { - def result = CompletableFuture.supplyAsync { - "done" - }.thenApplyAsync { result -> - runUnderTrace("child") { - result - } - } - return result - } - - then: - completableFuture.get() == "done" - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "child", span(0)) - } - } - } - - def "test thenCompose"() { - when: - CompletableFuture completableFuture = runUnderTrace("parent") { - def result = CompletableFuture.supplyAsync { - "done" - }.thenCompose { result -> - CompletableFuture.supplyAsync { - runUnderTrace("child") { - result - } - } - } - return result - } - - then: - completableFuture.get() == "done" - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "child", span(0)) - } - } - } - - def "test thenComposeAsync"() { - when: - CompletableFuture completableFuture = runUnderTrace("parent") { - def result = CompletableFuture.supplyAsync { - "done" - }.thenComposeAsync { result -> - CompletableFuture.supplyAsync { - runUnderTrace("child") { - result - } - } - } - return result - } - - then: - completableFuture.get() == "done" - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "child", span(0)) - } - } - } - - def "test compose and apply"() { - when: - CompletableFuture completableFuture = runUnderTrace("parent") { - def result = CompletableFuture.supplyAsync { - "do" - }.thenCompose { result -> - CompletableFuture.supplyAsync { - result + "ne" - } - }.thenApplyAsync { result -> - runUnderTrace("child") { - result - } - } - return result - } - - then: - completableFuture.get() == "done" - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "child", span(0)) - } - } - } - - static class AppendingSupplier implements Supplier { - String letter - - AppendingSupplier(String letter) { - this.letter = letter - } - - @Override - String get() { - getTestTracer().spanBuilder("appendingSupplier").startSpan().end() - return letter + "b" - } - } -} diff --git a/instrumentation/executors/src/test/groovy/ExecutorInstrumentationTest.groovy b/instrumentation/executors/src/test/groovy/ExecutorInstrumentationTest.groovy deleted file mode 100644 index f2649f8c3a..0000000000 --- a/instrumentation/executors/src/test/groovy/ExecutorInstrumentationTest.groovy +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import io.opentelemetry.sdk.trace.data.SpanData -import java.lang.reflect.InvocationTargetException -import java.util.concurrent.AbstractExecutorService -import java.util.concurrent.ArrayBlockingQueue -import java.util.concurrent.Callable -import java.util.concurrent.CompletableFuture -import java.util.concurrent.ExecutionException -import java.util.concurrent.ForkJoinPool -import java.util.concurrent.ForkJoinTask -import java.util.concurrent.Future -import java.util.concurrent.LinkedBlockingQueue -import java.util.concurrent.RejectedExecutionException -import java.util.concurrent.ScheduledThreadPoolExecutor -import java.util.concurrent.ThreadPoolExecutor -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException -import spock.lang.Shared - -class ExecutorInstrumentationTest extends AgentTestRunner { - static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { - it.setProperty("otel.instrumentation.executors.include", "ExecutorInstrumentationTest\$CustomThreadPoolExecutor") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - @Shared - def executeRunnable = { e, c -> e.execute((Runnable) c) } - @Shared - def executeForkJoinTask = { e, c -> e.execute((ForkJoinTask) c) } - @Shared - def submitRunnable = { e, c -> e.submit((Runnable) c) } - @Shared - def submitCallable = { e, c -> e.submit((Callable) c) } - @Shared - def submitForkJoinTask = { e, c -> e.submit((ForkJoinTask) c) } - @Shared - def invokeAll = { e, c -> e.invokeAll([(Callable) c]) } - @Shared - def invokeAllTimeout = { e, c -> e.invokeAll([(Callable) c], 10, TimeUnit.SECONDS) } - @Shared - def invokeAny = { e, c -> e.invokeAny([(Callable) c]) } - @Shared - def invokeAnyTimeout = { e, c -> e.invokeAny([(Callable) c], 10, TimeUnit.SECONDS) } - @Shared - def invokeForkJoinTask = { e, c -> e.invoke((ForkJoinTask) c) } - @Shared - def scheduleRunnable = { e, c -> e.schedule((Runnable) c, 10, TimeUnit.MILLISECONDS) } - @Shared - def scheduleCallable = { e, c -> e.schedule((Callable) c, 10, TimeUnit.MILLISECONDS) } - - def "#poolImpl '#name' propagates"() { - setup: - def pool = poolImpl - def m = method - - new Runnable() { - @Override - void run() { - runUnderTrace("parent") { - // this child will have a span - def child1 = new JavaAsyncChild() - // this child won't - def child2 = new JavaAsyncChild(false, false) - m(pool, child1) - m(pool, child2) - child1.waitForCompletion() - child2.waitForCompletion() - } - } - }.run() - - TEST_WRITER.waitForTraces(1) - List trace = TEST_WRITER.traces[0] - - expect: - TEST_WRITER.traces.size() == 1 - trace.size() == 2 - trace.get(0).name == "parent" - trace.get(1).name == "asyncChild" - trace.get(1).parentSpanId == trace.get(0).spanId - - cleanup: - if (pool?.hasProperty("shutdown")) { - pool?.shutdown() - } - - // Unfortunately, there's no simple way to test the cross product of methods/pools. - where: - name | method | poolImpl - "execute Runnable" | executeRunnable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "submit Runnable" | submitRunnable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "submit Callable" | submitCallable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "invokeAll" | invokeAll | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "invokeAll with timeout" | invokeAllTimeout | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "invokeAny" | invokeAny | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "invokeAny with timeout" | invokeAnyTimeout | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - - // Scheduled executor has additional methods and also may get disabled because it wraps tasks - "execute Runnable" | executeRunnable | new ScheduledThreadPoolExecutor(1) - "submit Runnable" | submitRunnable | new ScheduledThreadPoolExecutor(1) - "submit Callable" | submitCallable | new ScheduledThreadPoolExecutor(1) - "invokeAll" | invokeAll | new ScheduledThreadPoolExecutor(1) - "invokeAll with timeout" | invokeAllTimeout | new ScheduledThreadPoolExecutor(1) - "invokeAny" | invokeAny | new ScheduledThreadPoolExecutor(1) - "invokeAny with timeout" | invokeAnyTimeout | new ScheduledThreadPoolExecutor(1) - "schedule Runnable" | scheduleRunnable | new ScheduledThreadPoolExecutor(1) - "schedule Callable" | scheduleCallable | new ScheduledThreadPoolExecutor(1) - - // ForkJoinPool has additional set of method overloads for ForkJoinTask to deal with - "execute Runnable" | executeRunnable | new ForkJoinPool() - "execute ForkJoinTask" | executeForkJoinTask | new ForkJoinPool() - "submit Runnable" | submitRunnable | new ForkJoinPool() - "submit Callable" | submitCallable | new ForkJoinPool() - "submit ForkJoinTask" | submitForkJoinTask | new ForkJoinPool() - "invoke ForkJoinTask" | invokeForkJoinTask | new ForkJoinPool() - "invokeAll" | invokeAll | new ForkJoinPool() - "invokeAll with timeout" | invokeAllTimeout | new ForkJoinPool() - "invokeAny" | invokeAny | new ForkJoinPool() - "invokeAny with timeout" | invokeAnyTimeout | new ForkJoinPool() - - // CustomThreadPoolExecutor would normally be disabled except enabled above. - "execute Runnable" | executeRunnable | new CustomThreadPoolExecutor() - "submit Runnable" | submitRunnable | new CustomThreadPoolExecutor() - "submit Callable" | submitCallable | new CustomThreadPoolExecutor() - "invokeAll" | invokeAll | new CustomThreadPoolExecutor() - "invokeAll with timeout" | invokeAllTimeout | new CustomThreadPoolExecutor() - "invokeAny" | invokeAny | new CustomThreadPoolExecutor() - "invokeAny with timeout" | invokeAnyTimeout | new CustomThreadPoolExecutor() - - // Internal executor used by CompletableFuture - "execute Runnable" | executeRunnable | new CompletableFuture.ThreadPerTaskExecutor() - } - - def "#poolImpl '#name' wrap lambdas"() { - setup: - def pool = poolImpl - def m = method - def w = wrap - - JavaAsyncChild child = new JavaAsyncChild(true, true) - new Runnable() { - @Override - void run() { - runUnderTrace("parent") { - m(pool, w(child)) - } - } - }.run() - // We block in child to make sure spans close in predictable order - child.unblock() - child.waitForCompletion() - - TEST_WRITER.waitForTraces(1) - List trace = TEST_WRITER.traces[0] - - expect: - TEST_WRITER.traces.size() == 1 - trace.size() == 2 - trace.get(0).name == "parent" - trace.get(1).name == "asyncChild" - trace.get(1).parentSpanId == trace.get(0).spanId - - cleanup: - pool?.shutdown() - - where: - name | method | wrap | poolImpl - "execute Runnable" | executeRunnable | { LambdaGen.wrapRunnable(it) } | new ScheduledThreadPoolExecutor(1) - "submit Runnable" | submitRunnable | { LambdaGen.wrapRunnable(it) } | new ScheduledThreadPoolExecutor(1) - "submit Callable" | submitCallable | { LambdaGen.wrapCallable(it) } | new ScheduledThreadPoolExecutor(1) - "schedule Runnable" | scheduleRunnable | { LambdaGen.wrapRunnable(it) } | new ScheduledThreadPoolExecutor(1) - "schedule Callable" | scheduleCallable | { LambdaGen.wrapCallable(it) } | new ScheduledThreadPoolExecutor(1) - } - - def "#poolImpl '#name' reports after canceled jobs"() { - setup: - def pool = poolImpl - def m = method - List children = new ArrayList<>() - List jobFutures = new ArrayList<>() - - new Runnable() { - @Override - void run() { - runUnderTrace("parent") { - try { - for (int i = 0; i < 20; ++i) { - // Our current instrumentation instrumentation does not behave very well - // if we try to reuse Callable/Runnable. Namely we would be getting 'orphaned' - // child traces sometimes since state can contain only one parent span - and - // we do not really have a good way for attributing work to correct parent span - // if we reuse Callable/Runnable. - // Solution for now is to never reuse a Callable/Runnable. - JavaAsyncChild child = new JavaAsyncChild(false, true) - children.add(child) - try { - Future f = m(pool, child) - jobFutures.add(f) - } catch (InvocationTargetException e) { - throw e.getCause() - } - } - } catch (RejectedExecutionException e) { - } - - for (Future f : jobFutures) { - f.cancel(false) - } - for (JavaAsyncChild child : children) { - child.unblock() - } - } - } - }.run() - - TEST_WRITER.waitForTraces(1) - - expect: - TEST_WRITER.traces.size() == 1 - - where: - name | method | poolImpl - "submit Runnable" | submitRunnable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - "submit Callable" | submitCallable | new ThreadPoolExecutor(1, 1, 1000, TimeUnit.NANOSECONDS, new ArrayBlockingQueue(1)) - - // Scheduled executor has additional methods and also may get disabled because it wraps tasks - "submit Runnable" | submitRunnable | new ScheduledThreadPoolExecutor(1) - "submit Callable" | submitCallable | new ScheduledThreadPoolExecutor(1) - "schedule Runnable" | scheduleRunnable | new ScheduledThreadPoolExecutor(1) - "schedule Callable" | scheduleCallable | new ScheduledThreadPoolExecutor(1) - - // ForkJoinPool has additional set of method overloads for ForkJoinTask to deal with - "submit Runnable" | submitRunnable | new ForkJoinPool() - "submit Callable" | submitCallable | new ForkJoinPool() - } - - static class CustomThreadPoolExecutor extends AbstractExecutorService { - volatile running = true - def workQueue = new LinkedBlockingQueue(10) - - def worker = new Runnable() { - void run() { - try { - while (running) { - def runnable = workQueue.take() - runnable.run() - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt() - } catch (Exception e) { - e.printStackTrace() - } - } - } - - def workerThread = new Thread(worker, "ExecutorTestThread") - - private CustomThreadPoolExecutor() { - workerThread.start() - } - - @Override - void shutdown() { - running = false - workerThread.interrupt() - } - - @Override - List shutdownNow() { - running = false - workerThread.interrupt() - return [] - } - - @Override - boolean isShutdown() { - return !running - } - - @Override - boolean isTerminated() { - return workerThread.isAlive() - } - - @Override - boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - workerThread.join(unit.toMillis(timeout)) - return true - } - - @Override - def Future submit(Callable task) { - def future = newTaskFor(task) - execute(future) - return future - } - - @Override - def Future submit(Runnable task, T result) { - def future = newTaskFor(task, result) - execute(future) - return future - } - - @Override - Future submit(Runnable task) { - def future = newTaskFor(task, null) - execute(future) - return future - } - - @Override - def List> invokeAll(Collection> tasks) throws InterruptedException { - return super.invokeAll(tasks) - } - - @Override - def List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException { - return super.invokeAll(tasks) - } - - @Override - def T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { - return super.invokeAny(tasks) - } - - @Override - def T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return super.invokeAny(tasks) - } - - @Override - void execute(Runnable command) { - workQueue.put(command) - } - } -} diff --git a/instrumentation/executors/src/test/groovy/ModuleInjectionTest.groovy b/instrumentation/executors/src/test/groovy/ModuleInjectionTest.groovy deleted file mode 100644 index bda4407bf6..0000000000 --- a/instrumentation/executors/src/test/groovy/ModuleInjectionTest.groovy +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import javax.swing.* - -/** - * This class tests that we correctly add module references when instrumenting - */ -class ModuleInjectionTest extends AgentTestRunner { - /** - * There's nothing special about RepaintManager other than - * it's in a module (java.desktop) that doesn't read the "unnamed module" and it - * creates an instrumented runnable in its constructor - */ - def "test instrumenting java.desktop class"() { - when: - new RepaintManager() - - then: - noExceptionThrown() - } -} diff --git a/instrumentation/executors/src/test/java/JavaAsyncChild.java b/instrumentation/executors/src/test/java/JavaAsyncChild.java deleted file mode 100644 index c0f52f0d01..0000000000 --- a/instrumentation/executors/src/test/java/JavaAsyncChild.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.atomic.AtomicBoolean; - -public class JavaAsyncChild extends ForkJoinTask implements Runnable, Callable { - private static final Tracer TRACER = OpenTelemetry.getGlobalTracer("io.opentelemetry.auto"); - - private final AtomicBoolean blockThread; - private final boolean doTraceableWork; - private final CountDownLatch latch = new CountDownLatch(1); - - public JavaAsyncChild() { - this(true, false); - } - - @Override - public Object getRawResult() { - return null; - } - - @Override - protected void setRawResult(Object value) {} - - @Override - protected boolean exec() { - runImpl(); - return true; - } - - public JavaAsyncChild(boolean doTraceableWork, boolean blockThread) { - this.doTraceableWork = doTraceableWork; - this.blockThread = new AtomicBoolean(blockThread); - } - - public void unblock() { - blockThread.set(false); - } - - @Override - public void run() { - runImpl(); - } - - @Override - public Object call() { - runImpl(); - return null; - } - - public void waitForCompletion() throws InterruptedException { - latch.await(); - } - - private void runImpl() { - while (blockThread.get()) { - // busy-wait to block thread - } - if (doTraceableWork) { - asyncChild(); - } - latch.countDown(); - } - - private void asyncChild() { - TRACER.spanBuilder("asyncChild").startSpan().end(); - } -} diff --git a/instrumentation/executors/src/test/java/LambdaGen.java b/instrumentation/executors/src/test/java/LambdaGen.java deleted file mode 100644 index d715d8a09e..0000000000 --- a/instrumentation/executors/src/test/java/LambdaGen.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.Callable; - -class LambdaGen { - - static Callable wrapCallable(Callable callable) { - return () -> callable.call(); - } - - static Runnable wrapRunnable(Runnable runnable) { - return () -> runnable.run(); - } -} diff --git a/instrumentation/external-annotations/external-annotations.gradle b/instrumentation/external-annotations/external-annotations.gradle deleted file mode 100644 index b1800de8af..0000000000 --- a/instrumentation/external-annotations/external-annotations.gradle +++ /dev/null @@ -1,40 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk = true - } -} - -dependencies { - testImplementation group: 'com.newrelic.agent.java', name: 'newrelic-api', version: '5.14.0' - testImplementation(group: 'io.opentracing.contrib.dropwizard', name: 'dropwizard-opentracing', version: '0.2.2') { - transitive = false - } - testImplementation group: 'com.signalfx.public', name: 'signalfx-trace-api', version: '0.48.0-sfx1' - //Old and new versions of kamon use different packages for Trace annotation - testImplementation(group: 'io.kamon', name: 'kamon-annotation_2.11', version: '0.6.7') { - transitive = false - } - testImplementation group: 'io.kamon', name: 'kamon-annotation-api', version: '2.1.4' - testImplementation group: 'com.appoptics.agent.java', name: 'appoptics-sdk', version: '6.20.1' - testImplementation group: 'com.tracelytics.agent.java', name: 'tracelytics-api', version: '5.0.10' - testImplementation(group: 'org.springframework.cloud', name: 'spring-cloud-sleuth-core', version: '2.2.4.RELEASE') { - transitive = false - } -} - -test { - filter { - excludeTestsMatching 'TraceProvidersTest' - } -} - -// Needs a fresh classloader. -// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/919 -def testTraceProviders = tasks.register('testTraceProviders', Test) { - filter { - includeTestsMatching 'TraceProvidersTest' - } -} -test.dependsOn(testTraceProviders) diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAdvice.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAdvice.java deleted file mode 100644 index 4ae3942772..0000000000 --- a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAdvice.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.extannotations; - -import static io.opentelemetry.javaagent.instrumentation.extannotations.TraceAnnotationTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import net.bytebuddy.asm.Advice; - -public class TraceAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Origin Method method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(method); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } -} diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAnnotationTracer.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAnnotationTracer.java deleted file mode 100644 index 3d23027f7d..0000000000 --- a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAnnotationTracer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.extannotations; - -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; - -public class TraceAnnotationTracer extends BaseTracer { - private static final TraceAnnotationTracer TRACER = new TraceAnnotationTracer(); - - public static TraceAnnotationTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.external-annotations"; - } -} diff --git a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAnnotationsInstrumentationModule.java b/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAnnotationsInstrumentationModule.java deleted file mode 100644 index e85bb172c3..0000000000 --- a/instrumentation/external-annotations/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/TraceAnnotationsInstrumentationModule.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.extannotations; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.none; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.google.auto.service.AutoService; -import com.google.common.collect.Sets; -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.bytebuddy.description.ByteCodeElement; -import net.bytebuddy.description.NamedElement; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@AutoService(InstrumentationModule.class) -public class TraceAnnotationsInstrumentationModule extends InstrumentationModule { - private static final Logger log = - LoggerFactory.getLogger(TraceAnnotationsInstrumentationModule.class); - - private static final String PACKAGE_CLASS_NAME_REGEX = "[\\w.$]+"; - - static final String CONFIG_FORMAT = - "(?:\\s*" - + PACKAGE_CLASS_NAME_REGEX - + "\\s*;)*\\s*" - + PACKAGE_CLASS_NAME_REGEX - + "\\s*;?\\s*"; - - private static final String[] DEFAULT_ANNOTATIONS = - new String[] { - "com.appoptics.api.ext.LogMethod", - "com.newrelic.api.agent.Trace", - "com.signalfx.tracing.api.Trace", - "com.tracelytics.api.ext.LogMethod", - "datadog.trace.api.Trace", - "io.opentracing.contrib.dropwizard.Trace", - "kamon.annotation.Trace", - "kamon.annotation.api.Trace", - "org.springframework.cloud.sleuth.annotation.NewSpan" - }; - - private static final String TRACE_ANNOTATIONS_CONFIG = - "otel.instrumentation.external-annotations.include"; - private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG = - "otel.instrumentation.external-annotations.exclude-methods"; - - public TraceAnnotationsInstrumentationModule() { - super("external-annotations"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AnnotatedMethodsInstrumentation()); - } - - public static class AnnotatedMethodsInstrumentation implements TypeInstrumentation { - private final Set additionalTraceAnnotations; - private final ElementMatcher.Junction classLoaderOptimization; - private final ElementMatcher.Junction traceAnnotationMatcher; - /** This matcher matches all methods that should be excluded from transformation. */ - private final ElementMatcher.Junction excludedMethodsMatcher; - - public AnnotatedMethodsInstrumentation() { - additionalTraceAnnotations = configureAdditionalTraceAnnotations(Config.get()); - - if (additionalTraceAnnotations.isEmpty()) { - classLoaderOptimization = none(); - traceAnnotationMatcher = none(); - } else { - ElementMatcher.Junction classLoaderMatcher = null; - ElementMatcher.Junction methodTraceMatcher = null; - for (String annotationName : additionalTraceAnnotations) { - if (methodTraceMatcher == null) { - classLoaderMatcher = hasClassesNamed(annotationName); - methodTraceMatcher = named(annotationName); - } else { - classLoaderMatcher = classLoaderMatcher.or(hasClassesNamed(annotationName)); - methodTraceMatcher = methodTraceMatcher.or(named(annotationName)); - } - } - this.classLoaderOptimization = classLoaderMatcher; - this.traceAnnotationMatcher = methodTraceMatcher; - } - - excludedMethodsMatcher = configureExcludedMethods(); - } - - @Override - public ElementMatcher classLoaderOptimization() { - return classLoaderOptimization; - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType(declaresMethod(isAnnotatedWith(traceAnnotationMatcher))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isAnnotatedWith(traceAnnotationMatcher).and(not(excludedMethodsMatcher)), - TraceAdvice.class.getName()); - } - - private static Set configureAdditionalTraceAnnotations(Config config) { - String configString = config.getProperty(TRACE_ANNOTATIONS_CONFIG); - if (configString == null) { - return Collections.unmodifiableSet(Sets.newHashSet(DEFAULT_ANNOTATIONS)); - } else if (configString.isEmpty()) { - return Collections.emptySet(); - } else if (!configString.matches(CONFIG_FORMAT)) { - log.warn( - "Invalid trace annotations config '{}'. Must match 'package.Annotation$Name;*'.", - configString); - return Collections.emptySet(); - } else { - Set annotations = Sets.newHashSet(); - String[] annotationClasses = configString.split(";", -1); - for (String annotationClass : annotationClasses) { - if (!annotationClass.trim().isEmpty()) { - annotations.add(annotationClass.trim()); - } - } - return Collections.unmodifiableSet(annotations); - } - } - - /** - * Returns a matcher for all methods that should be excluded from auto-instrumentation by - * annotation-based advices. - */ - private static ElementMatcher.Junction configureExcludedMethods() { - ElementMatcher.Junction result = none(); - - Map> excludedMethods = - MethodsConfigurationParser.parse( - Config.get().getProperty(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); - for (Map.Entry> entry : excludedMethods.entrySet()) { - String className = entry.getKey(); - ElementMatcher.Junction classMather = - isDeclaredBy(ElementMatchers.named(className)); - - ElementMatcher.Junction excludedMethodsMatcher = none(); - for (String methodName : entry.getValue()) { - excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName)); - } - - result = result.or(classMather.and(excludedMethodsMatcher)); - } - - return result; - } - } -} diff --git a/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy b/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy deleted file mode 100644 index 516c37fea7..0000000000 --- a/instrumentation/external-annotations/src/test/groovy/ConfiguredTraceAnnotationsTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import io.opentelemetry.test.annotation.SayTracedHello -import java.util.concurrent.Callable - -class ConfiguredTraceAnnotationsTest extends AgentTestRunner { - static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { - it.setProperty("otel.instrumentation.external-annotations.include", - "package.Class\$Name;${OuterClass.InterestingMethod.name}") - } - - def specCleanup() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - def "method with disabled NewRelic annotation should be ignored"() { - setup: - SayTracedHello.fromCallableWhenDisabled() - - expect: - TEST_WRITER.traces == [] - } - - def "method with custom annotation should be traced"() { - expect: - new AnnotationTracedCallable().call() == "Hello!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "AnnotationTracedCallable.call" - attributes { - } - } - } - } - } - - static class AnnotationTracedCallable implements Callable { - @OuterClass.InterestingMethod - @Override - String call() throws Exception { - return "Hello!" - } - } -} diff --git a/instrumentation/external-annotations/src/test/groovy/IncludeTest.groovy b/instrumentation/external-annotations/src/test/groovy/IncludeTest.groovy deleted file mode 100644 index 745c79dfb6..0000000000 --- a/instrumentation/external-annotations/src/test/groovy/IncludeTest.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.api.config.Config.normalizePropertyName -import static io.opentelemetry.javaagent.instrumentation.extannotations.TraceAnnotationsInstrumentationModule.DEFAULT_ANNOTATIONS - -import io.opentelemetry.instrumentation.api.config.Config -import io.opentelemetry.javaagent.instrumentation.extannotations.TraceAnnotationsInstrumentationModule -import spock.lang.Specification - -class IncludeTest extends Specification { - - def "test configuration #value"() { - setup: - Config config - if (value) { - config = Config.create([ - (normalizePropertyName("otel.instrumentation.external-annotations.include")): value - ]) - } else { - config = Config.DEFAULT - } - - expect: - TraceAnnotationsInstrumentationModule.AnnotatedMethodsInstrumentation.configureAdditionalTraceAnnotations(config) == expected.toSet() - - where: - value | expected - null | DEFAULT_ANNOTATIONS.toList() - " " | [] - "some.Invalid[]" | [] - "some.package.ClassName " | ["some.package.ClassName"] - " some.package.Class\$Name" | ["some.package.Class\$Name"] - " ClassName " | ["ClassName"] - "ClassName" | ["ClassName"] - "Class\$1;Class\$2;" | ["Class\$1", "Class\$2"] - "Duplicate ;Duplicate ;Duplicate; " | ["Duplicate"] - } - -} diff --git a/instrumentation/external-annotations/src/test/groovy/TraceAnnotationsTest.groovy b/instrumentation/external-annotations/src/test/groovy/TraceAnnotationsTest.groovy deleted file mode 100644 index 453ebd316a..0000000000 --- a/instrumentation/external-annotations/src/test/groovy/TraceAnnotationsTest.groovy +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.test.annotation.SayTracedHello -import io.opentracing.contrib.dropwizard.Trace -import java.util.concurrent.Callable - -class TraceAnnotationsTest extends AgentTestRunner { - - def "test simple case annotations"() { - setup: - // Test single span in new trace - SayTracedHello.sayHello() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SayTracedHello.sayHello" - hasNoParent() - errored false - attributes { - "myattr" "test" - } - } - } - } - } - - def "test complex case annotations"() { - when: - // Test new trace with 2 children spans - SayTracedHello.sayHelloSayHa() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "SayTracedHello.sayHelloSayHa" - hasNoParent() - errored false - attributes { - "myattr" "test2" - } - } - span(1) { - name "SayTracedHello.sayHello" - childOf span(0) - errored false - attributes { - "myattr" "test" - } - } - span(2) { - name "SayTracedHello.sayHello" - childOf span(0) - errored false - attributes { - "myattr" "test" - } - } - } - } - } - - def "test exception exit"() { - setup: - Throwable error = null - try { - SayTracedHello.sayError() - } catch (final Throwable ex) { - error = ex - } - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SayTracedHello.sayError" - errored true - errorEvent(error.class) - } - } - } - } - - def "test annonymous class annotations"() { - setup: - // Test anonymous classes with package. - SayTracedHello.fromCallable() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SayTracedHello\$1.call" - attributes { - } - } - } - } - - when: - // Test anonymous classes with no package. - new Callable() { - @Trace - @Override - String call() throws Exception { - return "Howdy!" - } - }.call() - - then: - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SayTracedHello\$1.call" - attributes { - } - } - trace(1, 1) { - span(0) { - name "TraceAnnotationsTest\$1.call" - attributes { - } - } - } - } - } - } -} diff --git a/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy b/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy deleted file mode 100644 index b6c59686ef..0000000000 --- a/instrumentation/external-annotations/src/test/groovy/TraceProvidersTest.groovy +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.test.annotation.SayTracedHello - -/** - * This test verifies that Otel supports various 3rd-party trace annotations - */ -class TraceProvidersTest extends AgentTestRunner { - - def "should support #provider"(String provider) { - setup: - new SayTracedHello()."${provider.toLowerCase()}"() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SayTracedHello.${provider.toLowerCase()}" - hasNoParent() - errored false - attributes { - "providerAttr" provider - } - } - } - } - - where: - provider << ["AppOptics", "Datadog", "Dropwizard", "KamonOld", "KamonNew", "NewRelic", "SignalFx", "Sleuth", "Tracelytics"] - } - -} diff --git a/instrumentation/external-annotations/src/test/groovy/TracedMethodsExclusionTest.groovy b/instrumentation/external-annotations/src/test/groovy/TracedMethodsExclusionTest.groovy deleted file mode 100644 index f1daffe41b..0000000000 --- a/instrumentation/external-annotations/src/test/groovy/TracedMethodsExclusionTest.groovy +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import io.opentracing.contrib.dropwizard.Trace - -class TracedMethodsExclusionTest extends AgentTestRunner { - static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { - it.setProperty("otel.instrumentation.external-annotations.exclude-methods", - "${TestClass.name}[excluded,annotatedButExcluded]") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - static class TestClass { - //This method is not mentioned in any configuration - String notMentioned() { - return "Hello!" - } - - //This method is both configured to be traced and to be excluded. Should NOT be traced. - String excluded() { - return "Hello!" - } - - //This method is annotated with annotation which usually results in a captured span - @Trace - String annotated() { - return "Hello!" - } - - //This method is annotated with annotation which usually results in a captured span, but is configured to be - //excluded. - @Trace - String annotatedButExcluded() { - return "Hello!" - } - } - - - //Baseline and assumption validation - def "Calling these methods should be traced"() { - expect: - new TestClass().annotated() == "Hello!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TestClass.annotated" - attributes { - } - } - } - } - } - - def "Not explicitly configured method should not be traced"() { - expect: - new TestClass().notMentioned() == "Hello!" - - and: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - } - - def "Method which is both annotated and excluded for tracing should NOT be traced"() { - expect: - new TestClass().excluded() == "Hello!" - - and: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - } - - def "Method exclusion should override tracing annotations"() { - expect: - new TestClass().annotatedButExcluded() == "Hello!" - - and: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - } -} diff --git a/instrumentation/external-annotations/src/test/java/OuterClass.java b/instrumentation/external-annotations/src/test/java/OuterClass.java deleted file mode 100644 index 5fb43c2330..0000000000 --- a/instrumentation/external-annotations/src/test/java/OuterClass.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -public class OuterClass { - - @Retention(RUNTIME) - @Target(METHOD) - public @interface InterestingMethod {} -} diff --git a/instrumentation/external-annotations/src/test/java/io/opentelemetry/test/annotation/SayTracedHello.java b/instrumentation/external-annotations/src/test/java/io/opentelemetry/test/annotation/SayTracedHello.java deleted file mode 100644 index 9b2993dd47..0000000000 --- a/instrumentation/external-annotations/src/test/java/io/opentelemetry/test/annotation/SayTracedHello.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.test.annotation; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; -import java.util.concurrent.Callable; - -public class SayTracedHello { - - private static final Tracer TRACER = OpenTelemetry.getGlobalTracer("io.opentelemetry.auto"); - - @com.appoptics.api.ext.LogMethod - public String appoptics() { - Span.current().setAttribute("providerAttr", "AppOptics"); - return "hello!"; - } - - @com.newrelic.api.agent.Trace - public String newrelic() { - Span.current().setAttribute("providerAttr", "NewRelic"); - return "hello!"; - } - - @com.signalfx.tracing.api.Trace - public String signalfx() { - Span.current().setAttribute("providerAttr", "SignalFx"); - return "hello!"; - } - - @com.tracelytics.api.ext.LogMethod - public String tracelytics() { - Span.current().setAttribute("providerAttr", "Tracelytics"); - return "hello!"; - } - - @datadog.trace.api.Trace - public String datadog() { - Span.current().setAttribute("providerAttr", "Datadog"); - return "hello!"; - } - - @io.opentracing.contrib.dropwizard.Trace - public String dropwizard() { - Span.current().setAttribute("providerAttr", "Dropwizard"); - return "hello!"; - } - - @kamon.annotation.Trace("spanName") - public String kamonold() { - Span.current().setAttribute("providerAttr", "KamonOld"); - return "hello!"; - } - - @kamon.annotation.api.Trace - public String kamonnew() { - Span.current().setAttribute("providerAttr", "KamonNew"); - return "hello!"; - } - - @org.springframework.cloud.sleuth.annotation.NewSpan - public String sleuth() { - Span.current().setAttribute("providerAttr", "Sleuth"); - return "hello!"; - } - - @io.opentracing.contrib.dropwizard.Trace - public static String sayHello() { - Span.current().setAttribute("myattr", "test"); - return "hello!"; - } - - @io.opentracing.contrib.dropwizard.Trace - public static String sayHelloSayHa() { - Span.current().setAttribute("myattr", "test2"); - return sayHello() + sayHello(); - } - - @io.opentracing.contrib.dropwizard.Trace - public static String sayError() { - throw new RuntimeException(); - } - - public static String fromCallable() { - return new Callable() { - @com.newrelic.api.agent.Trace - @Override - public String call() { - return "Howdy!"; - } - }.call(); - } - - public static String fromCallableWhenDisabled() { - return new Callable() { - @com.newrelic.api.agent.Trace - @Override - public String call() { - return "Howdy!"; - } - }.call(); - } -} diff --git a/instrumentation/finatra-2.9/finatra-2.9.gradle b/instrumentation/finatra-2.9/finatra-2.9.gradle deleted file mode 100644 index 024aac5cc4..0000000000 --- a/instrumentation/finatra-2.9/finatra-2.9.gradle +++ /dev/null @@ -1,42 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply from: "$rootDir/gradle/test-with-scala.gradle" - -apply plugin: 'org.unbroken-dome.test-sets' - -testSets { - // We need separate test sources to compile against latest Finatra. - latestDepTest -} - -muzzle { - // There are some weird library issues below 2.9 so can't assert inverse - pass { - group = 'com.twitter' - module = 'finatra-http_2.11' - versions = '[2.9.0,]' - } - - pass { - group = 'com.twitter' - module = 'finatra-http_2.12' - versions = '[2.9.0,]' - } -} - -dependencies { - // TODO(anuraaga): Something about library configuration doesn't work well with scala compilation - // here. - compileOnly group: 'com.twitter', name: 'finatra-http_2.11', version: '2.9.0' - - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation group: 'com.twitter', name: 'finatra-http_2.11', version: '19.12.0' - testImplementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.10' - // Required for older versions of finatra on JDKs >= 11 - testImplementation group: 'com.sun.activation', name: 'javax.activation', version: '1.2.0' - - latestDepTestImplementation group: 'com.twitter', name: 'finatra-http_2.11', version: '+' -} - -compileLatestDepTestGroovy { - classpath += files(sourceSets.latestDepTest.scala.classesDirectory) -} diff --git a/instrumentation/finatra-2.9/javaagent/src/latestDepTest/groovy/FinatraServerLatestTest.groovy b/instrumentation/finatra-2.9/javaagent/src/latestDepTest/groovy/FinatraServerLatestTest.groovy index eec705f2e4..b00ac252fd 100644 --- a/instrumentation/finatra-2.9/javaagent/src/latestDepTest/groovy/FinatraServerLatestTest.groovy +++ b/instrumentation/finatra-2.9/javaagent/src/latestDepTest/groovy/FinatraServerLatestTest.groovy @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import static io.opentelemetry.api.trace.Span.Kind.INTERNAL +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import com.twitter.app.lifecycle.Event import com.twitter.app.lifecycle.Observer diff --git a/instrumentation/finatra-2.9/javaagent/src/test/groovy/FinatraServerTest.groovy b/instrumentation/finatra-2.9/javaagent/src/test/groovy/FinatraServerTest.groovy index 727a182cba..951cb5dec8 100644 --- a/instrumentation/finatra-2.9/javaagent/src/test/groovy/FinatraServerTest.groovy +++ b/instrumentation/finatra-2.9/javaagent/src/test/groovy/FinatraServerTest.groovy @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import static io.opentelemetry.api.trace.Span.Kind.INTERNAL +import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS import com.twitter.finatra.http.HttpServer import com.twitter.util.Await diff --git a/instrumentation/finatra-2.9/src/latestDepTest/groovy/FinatraServerLatestTest.groovy b/instrumentation/finatra-2.9/src/latestDepTest/groovy/FinatraServerLatestTest.groovy deleted file mode 100644 index b00ac252fd..0000000000 --- a/instrumentation/finatra-2.9/src/latestDepTest/groovy/FinatraServerLatestTest.groovy +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import com.twitter.app.lifecycle.Event -import com.twitter.app.lifecycle.Observer -import com.twitter.finatra.http.HttpServer -import com.twitter.util.Await -import com.twitter.util.Closable -import com.twitter.util.Duration -import com.twitter.util.Promise -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.sdk.trace.data.SpanData - -class FinatraServerLatestTest extends HttpServerTest { - private static final Duration TIMEOUT = Duration.fromSeconds(5) - private static final Duration STARTUP_TIMEOUT = Duration.fromSeconds(20) - - static closeAndWait(Closable closable) { - if (closable != null) { - Await.ready(closable.close(), TIMEOUT) - } - } - - @Override - HttpServer startServer(int port) { - HttpServer testServer = new FinatraServer() - - // Starting the server is blocking so start it in a separate thread - Thread startupThread = new Thread({ - testServer.main("-admin.port=:0", "-http.port=:" + port) - }) - startupThread.setDaemon(true) - startupThread.start() - - Promise startupPromise = new Promise<>() - - testServer.withObserver(new Observer() { - @Override - void onSuccess(Event event) { - if (event == testServer.startupCompletionEvent()) { - startupPromise.setValue(true) - } - } - - void onEntry(Event event) { - - } - - @Override - void onFailure(Event stage, Throwable throwable) { - if (stage != Event.Close$.MODULE$) { - startupPromise.setException(throwable) - } - } - }) - - Await.result(startupPromise, STARTUP_TIMEOUT) - - return testServer - } - - @Override - boolean hasHandlerSpan() { - return true - } - - @Override - boolean testNotFound() { - // Resource name is set to "GET /notFound" - false - } - - @Override - void stopServer(HttpServer httpServer) { - Await.ready(httpServer.close(), TIMEOUT) - } - - @Override - void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) { - trace.span(index) { - name "FinatraController" - kind INTERNAL - childOf(parent as SpanData) - // Finatra doesn't propagate the stack trace or exception to the instrumentation - // so the normal errorAttributes() method can't be used - errored false - attributes { - } - } - } -} diff --git a/instrumentation/finatra-2.9/src/latestDepTest/scala/FinatraController.scala b/instrumentation/finatra-2.9/src/latestDepTest/scala/FinatraController.scala deleted file mode 100644 index b752bed614..0000000000 --- a/instrumentation/finatra-2.9/src/latestDepTest/scala/FinatraController.scala +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.twitter.finagle.http.{Request, Response} -import com.twitter.finatra.http.Controller -import com.twitter.util.Future -import groovy.lang.Closure -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ -import io.opentelemetry.instrumentation.test.base.HttpServerTest.controller - -class FinatraController extends Controller { - any(SUCCESS.getPath) { request: Request => - controller(SUCCESS, new Closure[Response](null) { - override def call(): Response = { - response.ok(SUCCESS.getBody) - } - }) - } - - any(ERROR.getPath) { request: Request => - controller(ERROR, new Closure[Response](null) { - override def call(): Response = { - response.internalServerError(ERROR.getBody) - } - }) - } - - any(QUERY_PARAM.getPath) { request: Request => - controller(QUERY_PARAM, new Closure[Response](null) { - override def call(): Response = { - response.ok(QUERY_PARAM.getBody) - } - }) - } - - any(EXCEPTION.getPath) { request: Request => - controller(EXCEPTION, new Closure[Future[Response]](null) { - override def call(): Future[Response] = { - throw new Exception(EXCEPTION.getBody) - } - }) - } - - any(REDIRECT.getPath) { request: Request => - controller(REDIRECT, new Closure[Response](null) { - override def call(): Response = { - response.found.location(REDIRECT.getBody) - } - }) - } -} diff --git a/instrumentation/finatra-2.9/src/latestDepTest/scala/FinatraServer.scala b/instrumentation/finatra-2.9/src/latestDepTest/scala/FinatraServer.scala deleted file mode 100644 index 9a7405e557..0000000000 --- a/instrumentation/finatra-2.9/src/latestDepTest/scala/FinatraServer.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.twitter.finagle.http.Request -import com.twitter.finatra.http.HttpServer -import com.twitter.finatra.http.filters.ExceptionMappingFilter -import com.twitter.finatra.http.routing.HttpRouter - -class FinatraServer extends HttpServer { - override protected def configureHttp(router: HttpRouter): Unit = { - router - .filter[ExceptionMappingFilter[Request]] - .add[FinatraController] - .exceptionMapper[ResponseSettingExceptionMapper] - } -} diff --git a/instrumentation/finatra-2.9/src/latestDepTest/scala/ResponseSettingExceptionMapper.scala b/instrumentation/finatra-2.9/src/latestDepTest/scala/ResponseSettingExceptionMapper.scala deleted file mode 100644 index dbc7841e47..0000000000 --- a/instrumentation/finatra-2.9/src/latestDepTest/scala/ResponseSettingExceptionMapper.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.twitter.finagle.http.{Request, Response} -import com.twitter.finatra.http.exceptions.ExceptionMapper -import com.twitter.finatra.http.response.ResponseBuilder -import javax.inject.{Inject, Singleton} - -@Singleton -class ResponseSettingExceptionMapper @Inject()(response: ResponseBuilder) - extends ExceptionMapper[Exception] { - - override def toResponse(request: Request, exception: Exception): Response = { - response.internalServerError(exception.getMessage) - } -} diff --git a/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentationModule.java b/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentationModule.java deleted file mode 100644 index 4fe6eecb67..0000000000 --- a/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraInstrumentationModule.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.finatra; - -import static io.opentelemetry.javaagent.instrumentation.finatra.FinatraTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import com.twitter.finagle.http.Response; -import com.twitter.finatra.http.contexts.RouteInfo; -import com.twitter.util.Future; -import com.twitter.util.FutureEventListener; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import scala.Some; - -@AutoService(InstrumentationModule.class) -public class FinatraInstrumentationModule extends InstrumentationModule { - public FinatraInstrumentationModule() { - super("finatra", "finatra-2.9"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new RouteInstrumentation()); - } - - public static class RouteInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.twitter.finatra.http.internal.routing.Route"); - } - - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("com.twitter.finatra.") - .and( - extendsClass(named("com.twitter.finatra.http.internal.routing.Route"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("handleMatch")) - .and(takesArguments(2)) - .and(takesArgument(0, named("com.twitter.finagle.http.Request"))), - FinatraInstrumentationModule.class.getName() + "$RouteAdvice"); - } - } - - public static class RouteAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope nameSpan( - @Advice.FieldValue("routeInfo") RouteInfo routeInfo, - @Advice.FieldValue("clazz") Class clazz) { - - Span serverSpan = BaseTracer.getCurrentServerSpan(); - if (serverSpan != null) { - serverSpan.updateName(routeInfo.path()); - } - - Span span = tracer().startSpan(clazz); - - return new SpanWithScope(span, span.makeCurrent()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void setupCallback( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Thrown Throwable throwable, - @Advice.Return Some> responseOption) { - - if (spanWithScope == null) { - return; - } - - Span span = spanWithScope.getSpan(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - spanWithScope.closeScope(); - return; - } - - responseOption.get().addEventListener(new Listener(spanWithScope)); - } - } - - public static class Listener implements FutureEventListener { - private final SpanWithScope spanWithScope; - - public Listener(SpanWithScope spanWithScope) { - this.spanWithScope = spanWithScope; - } - - @Override - public void onSuccess(Response response) { - Span span = spanWithScope.getSpan(); - tracer().end(span); - spanWithScope.closeScope(); - } - - @Override - public void onFailure(Throwable cause) { - Span span = spanWithScope.getSpan(); - tracer().endExceptionally(span, cause); - spanWithScope.closeScope(); - } - } -} diff --git a/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraTracer.java b/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraTracer.java deleted file mode 100644 index 0c408c0327..0000000000 --- a/instrumentation/finatra-2.9/src/main/java/io/opentelemetry/javaagent/instrumentation/finatra/FinatraTracer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.finatra; - -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; - -public class FinatraTracer extends BaseTracer { - private static final FinatraTracer TRACER = new FinatraTracer(); - - public static FinatraTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.finatra"; - } -} diff --git a/instrumentation/finatra-2.9/src/test/groovy/FinatraServerTest.groovy b/instrumentation/finatra-2.9/src/test/groovy/FinatraServerTest.groovy deleted file mode 100644 index 951cb5dec8..0000000000 --- a/instrumentation/finatra-2.9/src/test/groovy/FinatraServerTest.groovy +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import com.twitter.finatra.http.HttpServer -import com.twitter.util.Await -import com.twitter.util.Closable -import com.twitter.util.Duration -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.concurrent.TimeoutException - -class FinatraServerTest extends HttpServerTest { - private static final Duration TIMEOUT = Duration.fromSeconds(5) - private static final long STARTUP_TIMEOUT = 40 * 1000 - - static closeAndWait(Closable closable) { - if (closable != null) { - Await.ready(closable.close(), TIMEOUT) - } - } - - @Override - HttpServer startServer(int port) { - HttpServer testServer = new FinatraServer() - - // Starting the server is blocking so start it in a separate thread - Thread startupThread = new Thread({ - testServer.main("-admin.port=:0", "-http.port=:" + port) - }) - startupThread.setDaemon(true) - startupThread.start() - - long startupDeadline = System.currentTimeMillis() + STARTUP_TIMEOUT - while (!testServer.started()) { - if (System.currentTimeMillis() > startupDeadline) { - throw new TimeoutException("Timed out waiting for server startup") - } - } - - return testServer - } - - @Override - boolean hasHandlerSpan() { - return true - } - - @Override - boolean testNotFound() { - // Resource name is set to "GET /notFound" - false - } - - @Override - void stopServer(HttpServer httpServer) { - Await.ready(httpServer.close(), TIMEOUT) - } - - @Override - boolean testPathParam() { - true - } - - @Override - void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) { - trace.span(index) { - name "FinatraController" - kind INTERNAL - childOf(parent as SpanData) - // Finatra doesn't propagate the stack trace or exception to the instrumentation - // so the normal errorAttributes() method can't be used - errored false - attributes { - } - } - } -} diff --git a/instrumentation/finatra-2.9/src/test/scala/FinatraController.scala b/instrumentation/finatra-2.9/src/test/scala/FinatraController.scala deleted file mode 100644 index fbc801d907..0000000000 --- a/instrumentation/finatra-2.9/src/test/scala/FinatraController.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.twitter.finagle.http.{Request, Response} -import com.twitter.finatra.http.Controller -import com.twitter.util.Future -import groovy.lang.Closure -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ -import io.opentelemetry.instrumentation.test.base.HttpServerTest.controller - -class FinatraController extends Controller { - any(SUCCESS.getPath) { request: Request => - controller(SUCCESS, new Closure[Response](null) { - override def call(): Response = { - response.ok(SUCCESS.getBody) - } - }) - } - - any(ERROR.getPath) { request: Request => - controller(ERROR, new Closure[Response](null) { - override def call(): Response = { - response.internalServerError(ERROR.getBody) - } - }) - } - - any(QUERY_PARAM.getPath) { request: Request => - controller(QUERY_PARAM, new Closure[Response](null) { - override def call(): Response = { - response.ok(QUERY_PARAM.getBody) - } - }) - } - - any(EXCEPTION.getPath) { request: Request => - controller(EXCEPTION, new Closure[Future[Response]](null) { - override def call(): Future[Response] = { - throw new Exception(EXCEPTION.getBody) - } - }) - } - - any(REDIRECT.getPath) { request: Request => - controller(REDIRECT, new Closure[Response](null) { - override def call(): Response = { - response.found.location(REDIRECT.getBody) - } - }) - } - - any("/path/:id/param") { request: Request => - controller(PATH_PARAM, new Closure[Response](null) { - override def call(): Response = { - response.ok(request.params("id")) - } - }) - } -} diff --git a/instrumentation/finatra-2.9/src/test/scala/FinatraServer.scala b/instrumentation/finatra-2.9/src/test/scala/FinatraServer.scala deleted file mode 100644 index 9a7405e557..0000000000 --- a/instrumentation/finatra-2.9/src/test/scala/FinatraServer.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.twitter.finagle.http.Request -import com.twitter.finatra.http.HttpServer -import com.twitter.finatra.http.filters.ExceptionMappingFilter -import com.twitter.finatra.http.routing.HttpRouter - -class FinatraServer extends HttpServer { - override protected def configureHttp(router: HttpRouter): Unit = { - router - .filter[ExceptionMappingFilter[Request]] - .add[FinatraController] - .exceptionMapper[ResponseSettingExceptionMapper] - } -} diff --git a/instrumentation/finatra-2.9/src/test/scala/ResponseSettingExceptionMapper.scala b/instrumentation/finatra-2.9/src/test/scala/ResponseSettingExceptionMapper.scala deleted file mode 100644 index dbc7841e47..0000000000 --- a/instrumentation/finatra-2.9/src/test/scala/ResponseSettingExceptionMapper.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.twitter.finagle.http.{Request, Response} -import com.twitter.finatra.http.exceptions.ExceptionMapper -import com.twitter.finatra.http.response.ResponseBuilder -import javax.inject.{Inject, Singleton} - -@Singleton -class ResponseSettingExceptionMapper @Inject()(response: ResponseBuilder) - extends ExceptionMapper[Exception] { - - override def toResponse(request: Request, exception: Exception): Response = { - response.internalServerError(exception.getMessage) - } -} diff --git a/instrumentation/geode-1.4/geode-1.4.gradle b/instrumentation/geode-1.4/geode-1.4.gradle deleted file mode 100644 index 936fd7d6b7..0000000000 --- a/instrumentation/geode-1.4/geode-1.4.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.geode" - module = "geode-core" - versions = "[1.4.0,)" - } -} - -dependencies { - library group: 'org.apache.geode', name: 'geode-core', version: '1.4.0' -} diff --git a/instrumentation/geode-1.4/javaagent/src/test/groovy/PutGetTest.groovy b/instrumentation/geode-1.4/javaagent/src/test/groovy/PutGetTest.groovy index d3825460eb..68fc4c34f9 100644 --- a/instrumentation/geode-1.4/javaagent/src/test/groovy/PutGetTest.groovy +++ b/instrumentation/geode-1.4/javaagent/src/test/groovy/PutGetTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT import static io.opentelemetry.api.trace.Span.Kind.INTERNAL +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner import org.apache.geode.DataSerializable import org.apache.geode.cache.client.ClientCacheFactory import org.apache.geode.cache.client.ClientRegionShortcut diff --git a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentationModule.java b/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentationModule.java deleted file mode 100644 index 55f38a0ad3..0000000000 --- a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeInstrumentationModule.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.geode; - -import static io.opentelemetry.javaagent.instrumentation.geode.GeodeTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.geode.cache.Region; - -@AutoService(InstrumentationModule.class) -public class GeodeInstrumentationModule extends InstrumentationModule { - public GeodeInstrumentationModule() { - super("geode", "geode-1.4"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new RegionInstrumentation()); - } - - public static class RegionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.apache.geode.cache.Region"); - } - - @Override - public ElementMatcher typeMatcher() { - return hasInterface(named("org.apache.geode.cache.Region")); - } - - @Override - public Map, String> transformers() { - Map, String> map = new HashMap<>(2); - map.put( - isMethod() - .and( - named("clear") - .or(nameStartsWith("contains")) - .or(named("create")) - .or(named("destroy")) - .or(named("entrySet")) - .or(named("get")) - .or(named("getAll")) - .or(named("invalidate")) - .or(nameStartsWith("keySet")) - .or(nameStartsWith("put")) - .or(nameStartsWith("remove")) - .or(named("replace"))), - GeodeInstrumentationModule.class.getName() + "$SimpleAdvice"); - map.put( - isMethod() - .and(named("existsValue").or(named("query")).or(named("selectValue"))) - .and(takesArgument(0, named("java.lang.String"))), - GeodeInstrumentationModule.class.getName() + "$QueryAdvice"); - return map; - } - } - - public static class SimpleAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This Region thiz, - @Advice.Origin Method method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (CallDepthThreadLocalMap.incrementCallDepth(Region.class) > 0) { - return; - } - span = tracer().startSpan(method.getName(), thiz, null); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - - CallDepthThreadLocalMap.reset(Region.class); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } - - public static class QueryAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This Region thiz, - @Advice.Origin Method method, - @Advice.Argument(0) String query, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (CallDepthThreadLocalMap.incrementCallDepth(Region.class) > 0) { - return; - } - span = tracer().startSpan(method.getName(), thiz, query); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - - CallDepthThreadLocalMap.reset(Region.class); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeQueryNormalizer.java b/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeQueryNormalizer.java deleted file mode 100644 index 9dda03197f..0000000000 --- a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeQueryNormalizer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.geode; - -import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled; - -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class GeodeQueryNormalizer { - private static final Logger log = LoggerFactory.getLogger(GeodeQueryNormalizer.class); - private static final boolean NORMALIZATION_ENABLED = - isQueryNormalizationEnabled("geode", "geode-1.4"); - - public static String normalize(String query) { - if (!NORMALIZATION_ENABLED || query == null) { - return query; - } - try { - return SqlNormalizer.normalize(query); - } catch (ParseException e) { - log.debug("Could not normalize Geode query", e); - return null; - } - } - - private GeodeQueryNormalizer() {} -} diff --git a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java b/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java deleted file mode 100644 index 926e1eba11..0000000000 --- a/instrumentation/geode-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeTracer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.geode; - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.net.InetSocketAddress; -import org.apache.geode.cache.Region; - -public class GeodeTracer extends DatabaseClientTracer, String> { - private static final GeodeTracer TRACER = new GeodeTracer(); - - public static GeodeTracer tracer() { - return TRACER; - } - - public Span startSpan(String operation, Region connection, String query) { - String normalizedQuery = normalizeQuery(query); - - Span span = - tracer - .spanBuilder(operation) - .setSpanKind(CLIENT) - .setAttribute(SemanticAttributes.DB_SYSTEM, dbSystem(connection)) - .setAttribute(SemanticAttributes.DB_OPERATION, operation) - .startSpan(); - - onConnection(span, connection); - setNetSemanticConvention(span, connection); - onStatement(span, normalizedQuery); - - return span; - } - - @Override - protected String normalizeQuery(String query) { - return GeodeQueryNormalizer.normalize(query); - } - - @Override - protected String dbSystem(Region region) { - return DbSystem.GEODE; - } - - @Override - protected String dbName(Region region) { - return region.getName(); - } - - @Override - protected InetSocketAddress peerAddress(Region region) { - return null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.geode"; - } -} diff --git a/instrumentation/geode-1.4/src/test/groovy/PutGetTest.groovy b/instrumentation/geode-1.4/src/test/groovy/PutGetTest.groovy deleted file mode 100644 index 68fc4c34f9..0000000000 --- a/instrumentation/geode-1.4/src/test/groovy/PutGetTest.groovy +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.apache.geode.DataSerializable -import org.apache.geode.cache.client.ClientCacheFactory -import org.apache.geode.cache.client.ClientRegionShortcut -import spock.lang.Shared -import spock.lang.Unroll - -@Unroll -class PutGetTest extends AgentTestRunner { - @Shared - def cache = new ClientCacheFactory().create() - - @Shared - def regionFactory = cache.createClientRegionFactory(ClientRegionShortcut.LOCAL) - - @Shared - def region = regionFactory.create("test-region") - - def "test put and get"() { - when: - def cacheValue = runUnderTrace("someTrace") { - region.clear() - region.put(key, value) - region.get(key) - } - - then: - cacheValue == value - assertGeodeTrace("get", null) - - where: - key | value - 'Hello' | 'World' - 'Humpty' | 'Dumpty' - '1' | 'One' - 'One' | '1' - } - - def "test put and remove"() { - when: - runUnderTrace("someTrace") { - region.clear() - region.put(key, value) - region.remove(key) - } - - then: - region.size() == 0 - assertGeodeTrace("remove", null) - - where: - key | value - 'Hello' | 'World' - 'Humpty' | 'Dumpty' - '1' | 'One' - 'One' | '1' - } - - def "test query"() { - when: - def cacheValue = runUnderTrace("someTrace") { - region.clear() - region.put(key, value) - region.query("SELECT * FROM /test-region") - } - - then: - cacheValue.asList().size() - assertGeodeTrace("query", "SELECT * FROM /test-region") - - where: - key | value - 'Hello' | 'World' - 'Humpty' | 'Dumpty' - '1' | 'One' - 'One' | '1' - } - - def "test existsValue"() { - when: - def exists = runUnderTrace("someTrace") { - region.clear() - region.put(key, value) - region.existsValue("SELECT * FROM /test-region") - } - - then: - exists - assertGeodeTrace("existsValue", "SELECT * FROM /test-region") - - where: - key | value - 'Hello' | 'World' - 'Humpty' | 'Dumpty' - '1' | 'One' - 'One' | '1' - } - - def assertGeodeTrace(String verb, String query) { - assertTraces(1) { - trace(0, 4) { - span(0) { - name "someTrace" - kind INTERNAL - errored false - } - span(1) { - name "clear" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "geode" - "$SemanticAttributes.DB_NAME.key" "test-region" - "$SemanticAttributes.DB_OPERATION.key" "clear" - } - } - span(2) { - name "put" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "geode" - "$SemanticAttributes.DB_NAME.key" "test-region" - "$SemanticAttributes.DB_OPERATION.key" "put" - } - } - span(3) { - name verb - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "geode" - "$SemanticAttributes.DB_NAME.key" "test-region" - "$SemanticAttributes.DB_OPERATION.key" verb - if (query != null) { - "$SemanticAttributes.DB_STATEMENT.key" query - } - } - } - } - } - return true - } - - def "should sanitize geode query"() { - given: - def value = new Card(cardNumber: '1234432156788765', expDate: '10/2020') - - region.clear() - region.put(1, value) - TEST_WRITER.waitForTraces(2) - TEST_WRITER.clear() - - when: - def results = region.query("SELECT * FROM /test-region p WHERE p.expDate = '10/2020'") - - then: - results.toList() == [value] - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "query" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "geode" - "$SemanticAttributes.DB_NAME.key" "test-region" - "$SemanticAttributes.DB_OPERATION.key" "query" - "$SemanticAttributes.DB_STATEMENT.key" "SELECT * FROM /test-region p WHERE p.expDate = ?" - } - } - } - } - } - - static class Card implements DataSerializable { - String cardNumber - String expDate - - @Override - void toData(DataOutput dataOutput) throws IOException { - dataOutput.writeUTF(cardNumber) - dataOutput.writeUTF(expDate) - } - - @Override - void fromData(DataInput dataInput) throws IOException, ClassNotFoundException { - cardNumber = dataInput.readUTF() - expDate = dataInput.readUTF() - } - } -} diff --git a/instrumentation/google-http-client-1.19/google-http-client-1.19.gradle b/instrumentation/google-http-client-1.19/google-http-client-1.19.gradle deleted file mode 100644 index fe91fd200c..0000000000 --- a/instrumentation/google-http-client-1.19/google-http-client-1.19.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.google.http-client" - module = "google-http-client" - - // 1.19.0 is the first release. The versions before are betas and RCs - versions = "[1.19.0,)" - } -} - -dependencies { - library group: 'com.google.http-client', name: 'google-http-client', version: '1.19.0' -} diff --git a/instrumentation/google-http-client-1.19/javaagent/src/test/groovy/AbstractGoogleHttpClientTest.groovy b/instrumentation/google-http-client-1.19/javaagent/src/test/groovy/AbstractGoogleHttpClientTest.groovy index 426f138839..c9aff3d866 100644 --- a/instrumentation/google-http-client-1.19/javaagent/src/test/groovy/AbstractGoogleHttpClientTest.groovy +++ b/instrumentation/google-http-client-1.19/javaagent/src/test/groovy/AbstractGoogleHttpClientTest.groovy @@ -9,8 +9,8 @@ import com.google.api.client.http.GenericUrl import com.google.api.client.http.HttpRequest import com.google.api.client.http.HttpResponse import com.google.api.client.http.javanet.NetHttpTransport -import io.opentelemetry.instrumentation.test.base.HttpClientTest import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.base.HttpClientTest import spock.lang.Shared abstract class AbstractGoogleHttpClientTest extends HttpClientTest { diff --git a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java b/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java deleted file mode 100644 index 541b8ce5fc..0000000000 --- a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.googlehttpclient; - -import static io.opentelemetry.javaagent.instrumentation.googlehttpclient.GoogleHttpClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpResponse; -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class GoogleHttpClientInstrumentationModule extends InstrumentationModule { - public GoogleHttpClientInstrumentationModule() { - super("google-http-client", "google-http-client-1.19"); - } - - @Override - public Map contextStore() { - return singletonMap("com.google.api.client.http.HttpRequest", Context.class.getName()); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HttpRequestInstrumentation()); - } - - public static class HttpRequestInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - // HttpRequest is a final class. Only need to instrument it exactly - // Note: the rest of com.google.api is ignored in AdditionalLibraryIgnoresMatcher to speed - // things up - return named("com.google.api.client.http.HttpRequest"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(isPublic()).and(named("execute")).and(takesArguments(0)), - GoogleHttpClientInstrumentationModule.class.getName() + "$GoogleHttpClientAdvice"); - - transformers.put( - isMethod() - .and(isPublic()) - .and(named("executeAsync")) - .and(takesArguments(1)) - .and(takesArgument(0, (named("java.util.concurrent.Executor")))), - GoogleHttpClientInstrumentationModule.class.getName() + "$GoogleHttpClientAsyncAdvice"); - - return transformers; - } - } - - public static class GoogleHttpClientAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.This HttpRequest request, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - ContextStore contextStore = - InstrumentationContext.get(HttpRequest.class, Context.class); - Context context = contextStore.get(request); - - if (context == null) { - span = tracer().startSpan(request); - scope = tracer().startScope(span, request.getHeaders()); - // TODO (trask) ideally we could pass current context into startScope to avoid extra lookup - contextStore.put(request, Java8BytecodeBridge.currentContext()); - } else { - // span was created by GoogleHttpClientAsyncAdvice instrumentation below - span = Java8BytecodeBridge.spanFromContext(context); - scope = context.makeCurrent(); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return HttpResponse response, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - scope.close(); - - if (throwable == null) { - tracer().end(span, response); - } else { - tracer().endExceptionally(span, response, throwable); - } - // If HttpRequest.setThrowExceptionOnExecuteError is set to false, there are no exceptions - // for a failed request. Thus, check the response code - if (response != null && !response.isSuccessStatusCode()) { - span.setStatus(StatusCode.ERROR); - } - } - } - - public static class GoogleHttpClientAsyncAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.This HttpRequest request, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - span = tracer().startSpan(request); - scope = tracer().startScope(span, request.getHeaders()); - - // propagating the context manually here so this instrumentation will work with and without - // the executors instrumentation - ContextStore contextStore = - InstrumentationContext.get(HttpRequest.class, Context.class); - contextStore.put(request, Java8BytecodeBridge.currentContext()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientTracer.java b/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientTracer.java deleted file mode 100644 index f5bb9030bd..0000000000 --- a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientTracer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.googlehttpclient; - -import com.google.api.client.http.HttpHeaders; -import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpResponse; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; - -public class GoogleHttpClientTracer - extends HttpClientTracer { - private static final GoogleHttpClientTracer TRACER = new GoogleHttpClientTracer(); - - public static GoogleHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.google-http-client"; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.getRequestMethod(); - } - - @Override - protected URI url(HttpRequest httpRequest) throws URISyntaxException { - // Google uses %20 (space) instead of "+" for spaces in the fragment - // Add "+" back for consistency with the other http client instrumentations - String url = httpRequest.getUrl().build(); - String fixedUrl = url.replaceAll("%20", "+"); - return new URI(fixedUrl); - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.getStatusCode(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return header(httpRequest.getHeaders(), name); - } - - @Override - protected String responseHeader(HttpResponse httpResponse, String name) { - return header(httpResponse.getHeaders(), name); - } - - @Override - protected Setter getSetter() { - return HeadersInjectAdapter.SETTER; - } - - private static String header(HttpHeaders headers, String name) { - return headers.getFirstHeaderStringValue(name); - } -} diff --git a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/HeadersInjectAdapter.java b/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/HeadersInjectAdapter.java deleted file mode 100644 index c64be1516a..0000000000 --- a/instrumentation/google-http-client-1.19/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/HeadersInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.googlehttpclient; - -import com.google.api.client.http.HttpHeaders; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class HeadersInjectAdapter implements TextMapPropagator.Setter { - - public static final HeadersInjectAdapter SETTER = new HeadersInjectAdapter(); - - @Override - public void set(HttpHeaders carrier, String key, String value) { - carrier.put(key, value); - } -} diff --git a/instrumentation/google-http-client-1.19/src/test/groovy/AbstractGoogleHttpClientTest.groovy b/instrumentation/google-http-client-1.19/src/test/groovy/AbstractGoogleHttpClientTest.groovy deleted file mode 100644 index c9aff3d866..0000000000 --- a/instrumentation/google-http-client-1.19/src/test/groovy/AbstractGoogleHttpClientTest.groovy +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import com.google.api.client.http.GenericUrl -import com.google.api.client.http.HttpRequest -import com.google.api.client.http.HttpResponse -import com.google.api.client.http.javanet.NetHttpTransport -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.Shared - -abstract class AbstractGoogleHttpClientTest extends HttpClientTest { - - @Shared - def requestFactory = new NetHttpTransport().createRequestFactory() - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - doRequest(method, uri, headers, callback, false) - } - - int doRequest(String method, URI uri, Map headers, Closure callback, boolean throwExceptionOnError) { - GenericUrl genericUrl = new GenericUrl(uri) - - HttpRequest request = requestFactory.buildRequest(method, genericUrl, null) - request.connectTimeout = CONNECT_TIMEOUT_MS - - // GenericData::putAll method converts all known http headers to List - // and lowercase all other headers - def ci = request.getHeaders().getClassInfo() - request.getHeaders().putAll(headers.collectEntries { name, value - -> [(name): (ci.getFieldInfo(name) != null ? [value] : value.toLowerCase())] - }) - - request.setThrowExceptionOnExecuteError(throwExceptionOnError) - - HttpResponse response = executeRequest(request) - callback?.call() - - return response.getStatusCode() - } - - abstract HttpResponse executeRequest(HttpRequest request) - - @Override - boolean testCircularRedirects() { - // Circular redirects don't throw an exception with Google Http Client - return false - } - - def "error traces when exception is not thrown"() { - given: - def uri = server.address.resolve("/error") - - when: - def status = doRequest(method, uri) - - then: - status == 500 - assertTraces(1) { - trace(0, 2) { - span(0) { - kind CLIENT - errored true - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "${uri}" - "${SemanticAttributes.HTTP_METHOD.key()}" method - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 500 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - } - } - server.distributedRequestSpan(it, 1, span(0)) - } - } - - where: - method = "GET" - } -} diff --git a/instrumentation/google-http-client-1.19/src/test/groovy/GoogleHttpClientAsyncTest.groovy b/instrumentation/google-http-client-1.19/src/test/groovy/GoogleHttpClientAsyncTest.groovy deleted file mode 100644 index 9ae715a6fd..0000000000 --- a/instrumentation/google-http-client-1.19/src/test/groovy/GoogleHttpClientAsyncTest.groovy +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.google.api.client.http.HttpRequest -import com.google.api.client.http.HttpResponse -import spock.lang.Timeout - -@Timeout(5) -class GoogleHttpClientAsyncTest extends AbstractGoogleHttpClientTest { - def setup() { - TEST_WRITER.clear() - } - - @Override - HttpResponse executeRequest(HttpRequest request) { - return request.executeAsync().get() - } -} diff --git a/instrumentation/google-http-client-1.19/src/test/groovy/GoogleHttpClientTest.groovy b/instrumentation/google-http-client-1.19/src/test/groovy/GoogleHttpClientTest.groovy deleted file mode 100644 index c30bcd4c91..0000000000 --- a/instrumentation/google-http-client-1.19/src/test/groovy/GoogleHttpClientTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.google.api.client.http.HttpRequest -import com.google.api.client.http.HttpResponse -import spock.lang.Timeout - -@Timeout(5) -class GoogleHttpClientTest extends AbstractGoogleHttpClientTest { - @Override - HttpResponse executeRequest(HttpRequest request) { - return request.execute() - } -} diff --git a/instrumentation/grizzly-2.0/grizzly-2.0.gradle b/instrumentation/grizzly-2.0/grizzly-2.0.gradle deleted file mode 100644 index 959a491f77..0000000000 --- a/instrumentation/grizzly-2.0/grizzly-2.0.gradle +++ /dev/null @@ -1,21 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.glassfish.grizzly" - module = 'grizzly-http' - versions = "[2.0,)" - assertInverse = true - } -} - -dependencies { - compileOnly group: 'org.glassfish.grizzly', name: 'grizzly-http', version: '2.0' - - testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3' - testImplementation group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0' - testLibrary group: 'org.glassfish.jersey.containers', name: 'jersey-container-grizzly2-http', version: '2.0' - - latestDepTestLibrary group: 'org.glassfish.jersey.containers', name: 'jersey-container-grizzly2-http', version: '2.+' - latestDepTestLibrary group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.+' -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainAdvice.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainAdvice.java deleted file mode 100644 index e057aafb4d..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainAdvice.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import net.bytebuddy.asm.Advice; -import org.glassfish.grizzly.filterchain.FilterChainContext; - -public class DefaultFilterChainAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onFail( - @Advice.Argument(0) FilterChainContext ctx, @Advice.Argument(1) Throwable throwable) { - Span span = tracer().getServerSpan(ctx); - if (span != null) { - tracer().endExceptionally(span, throwable); - } - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java deleted file mode 100644 index 356ad2b00a..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/DefaultFilterChainInstrumentation.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -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.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class DefaultFilterChainInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.glassfish.grizzly.filterchain.DefaultFilterChain"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isMethod() - .and(isPrivate()) - .and(named("notifyFailure")) - .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) - .and(takesArgument(1, named("java.lang.Throwable"))), - DefaultFilterChainAdvice.class.getName()); - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/ExtractAdapter.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/ExtractAdapter.java deleted file mode 100644 index a827e5ca75..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/ExtractAdapter.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.glassfish.grizzly.http.HttpRequestPacket; - -public class ExtractAdapter implements TextMapPropagator.Getter { - public static final ExtractAdapter GETTER = new ExtractAdapter(); - - @Override - public Iterable keys(HttpRequestPacket request) { - return request.getHeaders().names(); - } - - @Override - public String get(HttpRequestPacket request, String key) { - return request.getHeader(key); - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterAdvice.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterAdvice.java deleted file mode 100644 index 42e2f9c2e4..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterAdvice.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import net.bytebuddy.asm.Advice; -import org.glassfish.grizzly.filterchain.BaseFilter; -import org.glassfish.grizzly.filterchain.FilterChainContext; - -public class FilterAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This BaseFilter it, - @Advice.Argument(0) FilterChainContext ctx, - @Advice.Local("otelScope") Scope scope) { - if (Java8BytecodeBridge.currentSpan().getSpanContext().isValid()) { - return; - } - - Context context = tracer().getServerContext(ctx); - if (context != null) { - scope = context.makeCurrent(); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit(@Advice.This BaseFilter it, @Advice.Local("otelScope") Scope scope) { - if (scope != null) { - scope.close(); - } - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java deleted file mode 100644 index 5265eded63..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterInstrumentation.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.hasSuperClass; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; - -public class FilterInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.glassfish.grizzly.filterchain.BaseFilter"); - } - - @Override - public ElementMatcher typeMatcher() { - return hasSuperClass(named("org.glassfish.grizzly.filterchain.BaseFilter")) - // HttpCodecFilter is instrumented in the server instrumentation - .and( - not( - ElementMatchers.named( - "org.glassfish.grizzly.http.HttpCodecFilter"))) - .and( - not( - ElementMatchers.named( - "org.glassfish.grizzly.http.HttpServerFilter"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("handleRead") - .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) - .and(isPublic()), - FilterAdvice.class.getName()); - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyHttpServerTracer.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyHttpServerTracer.java deleted file mode 100644 index d53ceadc18..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyHttpServerTracer.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer; -import java.net.URI; -import java.net.URISyntaxException; -import org.glassfish.grizzly.filterchain.FilterChainContext; -import org.glassfish.grizzly.http.HttpRequestPacket; -import org.glassfish.grizzly.http.HttpResponsePacket; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class GrizzlyHttpServerTracer - extends HttpServerTracer< - HttpRequestPacket, HttpResponsePacket, HttpRequestPacket, FilterChainContext> { - - private static final Logger log = LoggerFactory.getLogger(GrizzlyHttpServerTracer.class); - - private static final GrizzlyHttpServerTracer TRACER = new GrizzlyHttpServerTracer(); - - public static GrizzlyHttpServerTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequestPacket httpRequest) { - return httpRequest.getMethod().getMethodString(); - } - - @Override - protected String requestHeader(HttpRequestPacket httpRequestPacket, String name) { - return httpRequestPacket.getHeader(name); - } - - @Override - protected int responseStatus(HttpResponsePacket httpResponsePacket) { - return httpResponsePacket.getStatus(); - } - - @Override - protected void attachServerContext(Context context, FilterChainContext filterChainContext) { - filterChainContext.getAttributes().setAttribute(CONTEXT_ATTRIBUTE, context); - } - - @Override - public Context getServerContext(FilterChainContext filterChainContext) { - Object attribute = filterChainContext.getAttributes().getAttribute(CONTEXT_ATTRIBUTE); - return attribute instanceof Context ? (Context) attribute : null; - } - - @Override - protected String url(HttpRequestPacket httpRequest) { - try { - return new URI( - (httpRequest.isSecure() ? "https://" : "http://") - + httpRequest.serverName() - + ":" - + httpRequest.getServerPort() - + httpRequest.getRequestURI() - + (httpRequest.getQueryString() != null - ? "?" + httpRequest.getQueryString() - : "")) - .toString(); - } catch (URISyntaxException e) { - log.warn("Failed to construct request URI", e); - return null; - } - } - - @Override - protected String peerHostIP(HttpRequestPacket httpRequest) { - return httpRequest.getRemoteAddress(); - } - - @Override - protected String flavor(HttpRequestPacket connection, HttpRequestPacket request) { - return connection.getProtocolString(); - } - - @Override - protected Getter getGetter() { - return ExtractAdapter.GETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.grizzly"; - } - - @Override - protected Integer peerPort(HttpRequestPacket httpRequest) { - return httpRequest.getRemotePort(); - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java deleted file mode 100644 index ad1a980d24..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class GrizzlyInstrumentationModule extends InstrumentationModule { - public GrizzlyInstrumentationModule() { - super("grizzly", "grizzly-2.0"); - } - - @Override - public List typeInstrumentations() { - return asList( - new DefaultFilterChainInstrumentation(), - new FilterInstrumentation(), - new HttpCodecFilterInstrumentation(), - new HttpServerFilterInstrumentation()); - } - - @Override - protected boolean defaultEnabled() { - return false; - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterAdvice.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterAdvice.java deleted file mode 100644 index 2098cbafea..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterAdvice.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import java.lang.reflect.Method; -import net.bytebuddy.asm.Advice; -import org.glassfish.grizzly.filterchain.FilterChainContext; -import org.glassfish.grizzly.http.HttpHeader; -import org.glassfish.grizzly.http.HttpRequestPacket; - -public class HttpCodecFilterAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Origin Method method, - @Advice.Argument(0) FilterChainContext ctx, - @Advice.Argument(1) HttpHeader httpHeader) { - Context context = tracer().getServerContext(ctx); - - // only create a span if there isn't another one attached to the current ctx - // and if the httpHeader has been parsed into a HttpRequestPacket - if (context != null || !(httpHeader instanceof HttpRequestPacket)) { - return; - } - HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader; - Context extractedContext = tracer().startSpan(httpRequest, httpRequest, method); - Span span = Java8BytecodeBridge.spanFromContext(extractedContext); - - // We don't actually want to attach new context to this thread, as actual request will continue - // on some other thread. But we do want to attach that new context to FilterChainContext - tracer().startScope(span, ctx).close(); - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java deleted file mode 100644 index 2e8244d9c0..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterInstrumentation.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class HttpCodecFilterInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.glassfish.grizzly.http.HttpCodecFilter"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - // this is for 2.3 through 2.3.19 - transformers.put( - named("handleRead") - .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) - .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpPacketParsing"))) - .and(isPublic()), - HttpCodecFilterOldAdvice.class.getName()); - // this is for 2.3.20+ - transformers.put( - named("handleRead") - .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) - .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpHeader"))) - .and(isPublic()), - HttpCodecFilterAdvice.class.getName()); - return transformers; - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterOldAdvice.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterOldAdvice.java deleted file mode 100644 index 7e327ad148..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpCodecFilterOldAdvice.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import java.lang.reflect.Method; -import net.bytebuddy.asm.Advice; -import org.glassfish.grizzly.filterchain.FilterChainContext; -import org.glassfish.grizzly.http.HttpPacketParsing; -import org.glassfish.grizzly.http.HttpRequestPacket; - -public class HttpCodecFilterOldAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Origin Method method, - @Advice.Argument(0) FilterChainContext ctx, - @Advice.Argument(1) HttpPacketParsing httpHeader) { - Context context = tracer().getServerContext(ctx); - - // only create a span if there isn't another one attached to the current ctx - // and if the httpHeader has been parsed into a HttpRequestPacket - if (context != null || !(httpHeader instanceof HttpRequestPacket)) { - return; - } - HttpRequestPacket httpRequest = (HttpRequestPacket) httpHeader; - Context extractedContext = tracer().startSpan(httpRequest, httpRequest, method); - Span span = Java8BytecodeBridge.spanFromContext(extractedContext); - - // We don't actually want to attach new context to this thread, as actual request will continue - // on some other thread. But we do want to attach that new context to FilterChainContext - tracer().startScope(span, ctx).close(); - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterAdvice.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterAdvice.java deleted file mode 100644 index c6fd0b0f5c..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterAdvice.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static io.opentelemetry.javaagent.instrumentation.grizzly.GrizzlyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import net.bytebuddy.asm.Advice; -import org.glassfish.grizzly.filterchain.FilterChainContext; -import org.glassfish.grizzly.http.HttpResponsePacket; - -public class HttpServerFilterAdvice { - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(0) FilterChainContext ctx, @Advice.Argument(2) HttpResponsePacket response) { - Span span = tracer().getServerSpan(ctx); - if (span != null) { - tracer().end(span, response); - } - } -} diff --git a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java b/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java deleted file mode 100644 index ae769ca265..0000000000 --- a/instrumentation/grizzly-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpServerFilterInstrumentation.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.grizzly; - -import static net.bytebuddy.matcher.ElementMatchers.isPrivate; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class HttpServerFilterInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.glassfish.grizzly.http.HttpServerFilter"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - named("prepareResponse") - .and(takesArgument(0, named("org.glassfish.grizzly.filterchain.FilterChainContext"))) - .and(takesArgument(1, named("org.glassfish.grizzly.http.HttpRequestPacket"))) - .and(takesArgument(2, named("org.glassfish.grizzly.http.HttpResponsePacket"))) - .and(takesArgument(3, named("org.glassfish.grizzly.http.HttpContent"))) - .and(isPrivate()), - HttpServerFilterAdvice.class.getName()); - } -} diff --git a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyAsyncTest.groovy b/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyAsyncTest.groovy deleted file mode 100644 index f735b0e060..0000000000 --- a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyAsyncTest.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import javax.ws.rs.GET -import javax.ws.rs.Path -import javax.ws.rs.QueryParam -import javax.ws.rs.container.AsyncResponse -import javax.ws.rs.container.Suspended -import javax.ws.rs.core.Response -import org.glassfish.grizzly.http.server.HttpServer -import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory -import org.glassfish.jersey.server.ResourceConfig - -class GrizzlyAsyncTest extends GrizzlyTest { - - @Override - HttpServer startServer(int port) { - ResourceConfig rc = new ResourceConfig() - rc.register(SimpleExceptionMapper) - rc.register(AsyncServiceResource) - GrizzlyHttpServerFactory.createHttpServer(new URI("http://localhost:$port"), rc) - } - - @Path("/") - static class AsyncServiceResource { - private ExecutorService executor = Executors.newSingleThreadExecutor() - - @GET - @Path("success") - void success(@Suspended AsyncResponse ar) { - executor.execute { - controller(SUCCESS) { - ar.resume(Response.status(SUCCESS.status).entity(SUCCESS.body).build()) - } - } - } - - @GET - @Path("query") - Response query_param(@QueryParam("some") String param, @Suspended AsyncResponse ar) { - controller(QUERY_PARAM) { - ar.resume(Response.status(QUERY_PARAM.status).entity("some=$param".toString()).build()) - } - } - - @GET - @Path("redirect") - void redirect(@Suspended AsyncResponse ar) { - executor.execute { - controller(REDIRECT) { - ar.resume(Response.status(REDIRECT.status).location(new URI(REDIRECT.body)).build()) - } - } - } - - @GET - @Path("error-status") - void error(@Suspended AsyncResponse ar) { - executor.execute { - controller(ERROR) { - ar.resume(Response.status(ERROR.status).entity(ERROR.body).build()) - } - } - } - - @GET - @Path("exception") - void exception(@Suspended AsyncResponse ar) { - executor.execute { - try { - controller(EXCEPTION) { - throw new Exception(EXCEPTION.body) - } - } catch (Exception e) { - ar.resume(e) - } - } - } - } -} diff --git a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyFilterchainServerTest.groovy b/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyFilterchainServerTest.groovy deleted file mode 100644 index 8d65c6b6c2..0000000000 --- a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyFilterchainServerTest.groovy +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.AUTH_REQUIRED -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static java.lang.String.valueOf -import static java.nio.charset.Charset.defaultCharset -import static java.util.concurrent.TimeUnit.MILLISECONDS -import static org.glassfish.grizzly.memory.Buffers.wrap - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import java.util.concurrent.Executors -import org.glassfish.grizzly.filterchain.BaseFilter -import org.glassfish.grizzly.filterchain.FilterChain -import org.glassfish.grizzly.filterchain.FilterChainBuilder -import org.glassfish.grizzly.filterchain.FilterChainContext -import org.glassfish.grizzly.filterchain.NextAction -import org.glassfish.grizzly.filterchain.TransportFilter -import org.glassfish.grizzly.http.HttpContent -import org.glassfish.grizzly.http.HttpHeader -import org.glassfish.grizzly.http.HttpRequestPacket -import org.glassfish.grizzly.http.HttpResponsePacket -import org.glassfish.grizzly.http.HttpServerFilter -import org.glassfish.grizzly.http.server.HttpServer -import org.glassfish.grizzly.nio.transport.TCPNIOServerConnection -import org.glassfish.grizzly.nio.transport.TCPNIOTransport -import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder -import org.glassfish.grizzly.utils.DelayedExecutor -import org.glassfish.grizzly.utils.IdleTimeoutFilter - -class GrizzlyFilterchainServerTest extends HttpServerTest { - - static { - System.setProperty("otel.instrumentation.grizzly.enabled", "true") - } - - private TCPNIOTransport transport - private TCPNIOServerConnection serverConnection - - @Override - HttpServer startServer(int port) { - FilterChain filterChain = setUpFilterChain() - setUpTransport(filterChain) - - serverConnection = transport.bind("127.0.0.1", port) - transport.start() - return null - } - - @Override - void stopServer(HttpServer httpServer) { - transport.shutdownNow() - } - - @Override - boolean testException() { - // justification: grizzly async closes the channel which - // looks like a ConnectException to the client when this happens - false - } - - void setUpTransport(FilterChain filterChain) { - TCPNIOTransportBuilder transportBuilder = TCPNIOTransportBuilder.newInstance() - .setOptimizedForMultiplexing(true) - - transportBuilder.setTcpNoDelay(true) - transportBuilder.setKeepAlive(false) - transportBuilder.setReuseAddress(true) - transportBuilder.setServerConnectionBackLog(50) - transportBuilder.setServerSocketSoTimeout(80000) - - transport = transportBuilder.build() - transport.setProcessor(filterChain) - } - - FilterChain setUpFilterChain() { - return FilterChainBuilder.stateless() - .add(createTransportFilter()) - .add(createIdleTimeoutFilter()) - .add(new HttpServerFilter()) - .add(new LastFilter()) - .build() - } - - TransportFilter createTransportFilter() { - return new TransportFilter() - } - - IdleTimeoutFilter createIdleTimeoutFilter() { - return new IdleTimeoutFilter(new DelayedExecutor(Executors.newCachedThreadPool()), 80000, MILLISECONDS) - } - - static class LastFilter extends BaseFilter { - - @Override - NextAction handleRead(final FilterChainContext ctx) throws IOException { - if (ctx.getMessage() instanceof HttpContent) { - HttpContent httpContent = ctx.getMessage() - HttpHeader httpHeader = httpContent.getHttpHeader() - if (httpHeader instanceof HttpRequestPacket) { - HttpRequestPacket request = (HttpRequestPacket) httpContent.getHttpHeader() - ResponseParameters responseParameters = buildResponse(request) - HttpResponsePacket.Builder builder = HttpResponsePacket.builder(request) - .status(responseParameters.getStatus()) - .header("Content-Length", valueOf(responseParameters.getResponseBody().length)) - responseParameters.fillHeaders(builder) - HttpResponsePacket responsePacket = builder.build() - controller(responseParameters.getEndpoint()) { - ctx.write(HttpContent.builder(responsePacket) - .content(wrap(ctx.getMemoryManager(), responseParameters.getResponseBody())) - .build()) - } - } - } - return ctx.getStopAction() - } - - ResponseParameters buildResponse(HttpRequestPacket request) { - String uri = request.getRequestURI() - String requestParams = request.getQueryString() - String fullPath = uri + (requestParams != null ? "?" + requestParams : "") - - Map headers = new HashMap<>() - - HttpServerTest.ServerEndpoint endpoint - switch (fullPath) { - case "/success": - endpoint = SUCCESS - break - case "/redirect": - endpoint = REDIRECT - headers.put("location", REDIRECT.body) - break - case "/error-status": - endpoint = ERROR - break - case "/exception": - throw new Exception(EXCEPTION.body) - case "/notFound": - endpoint = NOT_FOUND - break - case "/query?some=query": - endpoint = QUERY_PARAM - break - case "/path/123/param": - endpoint = PATH_PARAM - break - case "/authRequired": - endpoint = AUTH_REQUIRED - break - default: - endpoint = NOT_FOUND - break - } - - int status = endpoint.status - String responseBody = endpoint == REDIRECT ? "" : endpoint.body - - byte[] responseBodyBytes = responseBody.getBytes(defaultCharset()) - return new ResponseParameters(endpoint, status, responseBodyBytes, headers) - } - - static class ResponseParameters { - Map headers - HttpServerTest.ServerEndpoint endpoint - int status - byte[] responseBody - - ResponseParameters(HttpServerTest.ServerEndpoint endpoint, - int status, - byte[] responseBody, - Map headers) { - this.endpoint = endpoint - this.status = status - this.responseBody = responseBody - this.headers = headers - } - - int getStatus() { - return status - } - - byte[] getResponseBody() { - return responseBody - } - - HttpServerTest.ServerEndpoint getEndpoint() { - return endpoint - } - - void fillHeaders(HttpResponsePacket.Builder builder) { - for (Map.Entry header : headers.entrySet()) { - builder.header(header.getKey(), header.getValue()) - } - } - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "HttpCodecFilter.handleRead" - } -} diff --git a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyIOStrategyTest.groovy b/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyIOStrategyTest.groovy deleted file mode 100644 index 6f12ee447a..0000000000 --- a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyIOStrategyTest.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.glassfish.grizzly.IOStrategy -import org.glassfish.grizzly.http.server.HttpServer -import org.glassfish.grizzly.strategies.LeaderFollowerNIOStrategy -import org.glassfish.grizzly.strategies.SameThreadIOStrategy -import org.glassfish.grizzly.strategies.SimpleDynamicNIOStrategy -import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory -import org.glassfish.jersey.server.ResourceConfig - -abstract class GrizzlyIOStrategyTest extends GrizzlyTest { - @Override - HttpServer startServer(int port) { - ResourceConfig rc = new ResourceConfig() - rc.register(SimpleExceptionMapper) - rc.register(ServiceResource) - def server = GrizzlyHttpServerFactory.createHttpServer(new URI("http://localhost:$port"), rc) - server.getListener("grizzly").getTransport().setIOStrategy(strategy()) - // Default in NIOTransportBuilder is WorkerThreadIOStrategy, so don't need to retest that.s - return server - } - - abstract IOStrategy strategy() -} - -class LeaderFollowerTest extends GrizzlyIOStrategyTest { - - @Override - IOStrategy strategy() { - return LeaderFollowerNIOStrategy.instance - } -} - -class SameThreadTest extends GrizzlyIOStrategyTest { - - @Override - IOStrategy strategy() { - return SameThreadIOStrategy.instance - } -} - -class SimpleDynamicTest extends GrizzlyIOStrategyTest { - - @Override - IOStrategy strategy() { - return SimpleDynamicNIOStrategy.instance - } -} diff --git a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyTest.groovy b/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyTest.groovy deleted file mode 100644 index 439e1400d3..0000000000 --- a/instrumentation/grizzly-2.0/src/test/groovy/GrizzlyTest.groovy +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import javax.ws.rs.GET -import javax.ws.rs.NotFoundException -import javax.ws.rs.Path -import javax.ws.rs.QueryParam -import javax.ws.rs.core.Response -import javax.ws.rs.ext.ExceptionMapper -import org.glassfish.grizzly.http.server.HttpServer -import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory -import org.glassfish.jersey.server.ResourceConfig - -class GrizzlyTest extends HttpServerTest { - - static { - System.setProperty("otel.instrumentation.grizzly.enabled", "true") - } - - @Override - HttpServer startServer(int port) { - ResourceConfig rc = new ResourceConfig() - rc.register(SimpleExceptionMapper) - rc.register(ServiceResource) - GrizzlyHttpServerFactory.createHttpServer(new URI("http://localhost:$port"), rc) - } - - @Override - void stopServer(HttpServer server) { - server.stop() - } - - static class SimpleExceptionMapper implements ExceptionMapper { - - @Override - Response toResponse(Throwable exception) { - if (exception instanceof NotFoundException) { - return exception.getResponse() - } - Response.status(500).entity(exception.message).build() - } - } - - @Path("/") - static class ServiceResource { - - @GET - @Path("success") - Response success() { - controller(SUCCESS) { - Response.status(SUCCESS.status).entity(SUCCESS.body).build() - } - } - - @GET - @Path("query") - Response query_param(@QueryParam("some") String param) { - controller(QUERY_PARAM) { - Response.status(QUERY_PARAM.status).entity("some=$param".toString()).build() - } - } - - @GET - @Path("redirect") - Response redirect() { - controller(REDIRECT) { - Response.status(REDIRECT.status).location(new URI(REDIRECT.body)).build() - } - } - - @GET - @Path("error-status") - Response error() { - controller(ERROR) { - Response.status(ERROR.status).entity(ERROR.body).build() - } - } - - @GET - @Path("exception") - Response exception() { - controller(EXCEPTION) { - throw new Exception(EXCEPTION.body) - } - return null - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "HttpCodecFilter.handleRead" - } - - @Override - boolean testException() { - // TODO(anuraaga): https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/807 - return false - } -} diff --git a/instrumentation/guava-10.0/guava-10.0.gradle b/instrumentation/guava-10.0/guava-10.0.gradle deleted file mode 100644 index 7c9ae527f0..0000000000 --- a/instrumentation/guava-10.0/guava-10.0.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.google.guava" - module = "guava" - versions = "[10.0,]" - assertInverse = true - } -} - -dependencies { - library group: 'com.google.guava', name: 'guava', version: '10.0' -} diff --git a/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java b/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java deleted file mode 100644 index 1117562e44..0000000000 --- a/instrumentation/guava-10.0/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.guava; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import com.google.common.util.concurrent.AbstractFuture; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.ExecutorInstrumentationUtils; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.RunnableWrapper; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executor; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; - -@AutoService(InstrumentationModule.class) -public class GuavaInstrumentationModule extends InstrumentationModule { - - public GuavaInstrumentationModule() { - super("guava", "guava-10.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ListenableFutureInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap(Runnable.class.getName(), State.class.getName()); - } - - public static class ListenableFutureInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("com.google.common.util.concurrent.AbstractFuture"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("addListener").and(ElementMatchers.takesArguments(Runnable.class, Executor.class)), - GuavaInstrumentationModule.class.getName() + "$AddListenerAdvice"); - } - } - - public static class AddListenerAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static State addListenerEnter( - @Advice.Argument(value = 0, readOnly = false) Runnable task) { - final Context context = Java8BytecodeBridge.currentContext(); - final Runnable newTask = RunnableWrapper.wrapIfNeeded(task); - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask)) { - task = newTask; - final ContextStore contextStore = - InstrumentationContext.get(Runnable.class, State.class); - return ExecutorInstrumentationUtils.setupState(contextStore, newTask, context); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void addListenerExit( - @Advice.Enter final State state, @Advice.Thrown final Throwable throwable) { - ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); - } - - private static void muzzleCheck(final AbstractFuture future) { - future.addListener(null, null); - } - } -} diff --git a/instrumentation/guava-10.0/src/test/groovy/ListenableFutureTest.groovy b/instrumentation/guava-10.0/src/test/groovy/ListenableFutureTest.groovy deleted file mode 100644 index 0e06d4ef36..0000000000 --- a/instrumentation/guava-10.0/src/test/groovy/ListenableFutureTest.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.google.common.util.concurrent.Futures -import com.google.common.util.concurrent.ListenableFuture -import com.google.common.util.concurrent.SettableFuture -import io.opentelemetry.instrumentation.test.base.AbstractPromiseTest -import java.util.concurrent.Executors -import spock.lang.Shared - -class ListenableFutureTest extends AbstractPromiseTest, ListenableFuture> { - @Shared - def executor = Executors.newFixedThreadPool(1) - - @Override - SettableFuture newPromise() { - return SettableFuture.create() - } - - @Override - ListenableFuture map(SettableFuture promise, Closure callback) { - return Futures.transform(promise, callback, executor) - } - - @Override - void onComplete(ListenableFuture promise, Closure callback) { - promise.addListener({ -> callback(promise.get()) }, executor) - } - - - @Override - void complete(SettableFuture promise, boolean value) { - promise.set(value) - } - - @Override - Boolean get(SettableFuture promise) { - return promise.get() - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/hibernate-3.3.gradle b/instrumentation/hibernate/hibernate-3.3/hibernate-3.3.gradle deleted file mode 100644 index bbc8be7351..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/hibernate-3.3.gradle +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Instrumentation for Hibernate between 3.5 and 4. - * Has the same logic as the Hibernate 4+ instrumentation, but is copied rather than sharing a codebase. This is because - * the root interface for Session/StatelessSession - SharedSessionContract - isn't present before version 4. So the - * instrumentation isn't able to reference it. - */ - -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.hibernate" - module = "hibernate-core" - versions = "[3.3.0.GA,4.0.0.Final)" - assertInverse = true - } -} - -dependencies { - library group: 'org.hibernate', name: 'hibernate-core', version: '3.3.0.GA' - - implementation project(':instrumentation:hibernate:hibernate-common') - - testImplementation project(':instrumentation:jdbc') - // Added to ensure cross compatibility: - testImplementation project(':instrumentation:hibernate:hibernate-4.0') - testImplementation project(':instrumentation:hibernate:hibernate-4.3') - - testLibrary group: 'org.hibernate', name: 'hibernate-core', version: '3.3.0.SP1' - testImplementation group: 'org.hibernate', name: 'hibernate-annotations', version: '3.4.0.GA' - testImplementation group: 'javassist', name: 'javassist', version: '+' - testImplementation group: 'com.h2database', name: 'h2', version: '1.4.197' - testImplementation "javax.xml.bind:jaxb-api:2.2.11" - testImplementation "com.sun.xml.bind:jaxb-core:2.2.11" - testImplementation "com.sun.xml.bind:jaxb-impl:2.2.11" - testImplementation "javax.activation:activation:1.1.1" - - latestDepTestLibrary group: 'org.hibernate', name: 'hibernate-core', version: '3.+' -} - -if (findProperty('testLatestDeps')) { - configurations { - // Needed for test, but for latestDepTest this would otherwise bundle a second incompatible version of hibernate-core. - testImplementation.exclude group: 'org.hibernate', module: 'hibernate-annotations' - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java deleted file mode 100644 index 6bf98e4a63..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/CriteriaInstrumentation.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Criteria; - -public class CriteriaInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Criteria"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.Criteria")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(namedOneOf("list", "uniqueResult", "scroll")), - CriteriaInstrumentation.class.getName() + "$CriteriaMethodAdvice"); - } - - public static class CriteriaMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod( - @Advice.This Criteria criteria, @Advice.Origin("#m") String name) { - - ContextStore contextStore = - InstrumentationContext.get(Criteria.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, criteria, "Criteria." + name, null, true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Thrown Throwable throwable, - @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object entity, - @Advice.Origin("#m") String name) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, "Criteria." + name, entity); - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java deleted file mode 100644 index 73a48894a3..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class HibernateInstrumentationModule extends InstrumentationModule { - - public HibernateInstrumentationModule() { - super("hibernate", "hibernate-3.3"); - } - - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return hasClassesNamed( - // Not in 4.0 - "org.hibernate.classic.Validatable", - // Not before 3.3.0.GA - "org.hibernate.transaction.JBossTransactionManagerLookup"); - } - - @Override - public List typeInstrumentations() { - return asList( - new CriteriaInstrumentation(), - new QueryInstrumentation(), - new SessionFactoryInstrumentation(), - new SessionInstrumentation(), - new TransactionInstrumentation()); - } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.Criteria", Context.class.getName()); - map.put("org.hibernate.Query", Context.class.getName()); - map.put("org.hibernate.Session", Context.class.getName()); - map.put("org.hibernate.StatelessSession", Context.class.getName()); - map.put("org.hibernate.Transaction", Context.class.getName()); - return Collections.unmodifiableMap(map); - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java deleted file mode 100644 index 5c7edd4e05..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/QueryInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Query; - -public class QueryInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Query"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.Query")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(namedOneOf("list", "executeUpdate", "uniqueResult", "iterate", "scroll")), - QueryInstrumentation.class.getName() + "$QueryMethodAdvice"); - } - - public static class QueryMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod(@Advice.This Query query) { - - ContextStore contextStore = - InstrumentationContext.get(Query.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, query, query.getQueryString(), null, true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, null, null); - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java deleted file mode 100644 index 2979ffd17d..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionFactoryInstrumentation.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Session; -import org.hibernate.StatelessSession; - -public class SessionFactoryInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.SessionFactory"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.SessionFactory")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(namedOneOf("openSession", "openStatelessSession")) - .and(takesArguments(0)) - .and( - returns( - namedOneOf("org.hibernate.Session", "org.hibernate.StatelessSession") - .or(hasInterface(named("org.hibernate.Session"))))), - SessionFactoryInstrumentation.class.getName() + "$SessionFactoryAdvice"); - } - - public static class SessionFactoryAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void openSession(@Advice.Return Object session) { - - Context context = Java8BytecodeBridge.currentContext(); - Span span = tracer().startSpan(context, "Session"); - - if (session instanceof Session) { - ContextStore contextStore = - InstrumentationContext.get(Session.class, Context.class); - contextStore.putIfAbsent((Session) session, context.with(span)); - } else if (session instanceof StatelessSession) { - ContextStore contextStore = - InstrumentationContext.get(StatelessSession.class, Context.class); - contextStore.putIfAbsent((StatelessSession) session, context.with(span)); - } - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java deleted file mode 100644 index 7389904d7b..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/SessionInstrumentation.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Criteria; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.StatelessSession; -import org.hibernate.Transaction; - -public class SessionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Session", "org.hibernate.StatelessSession"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface( - namedOneOf("org.hibernate.Session", "org.hibernate.StatelessSession")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(named("close")).and(takesArguments(0)), - SessionInstrumentation.class.getName() + "$SessionCloseAdvice"); - - // Session synchronous methods we want to instrument. - transformers.put( - isMethod() - .and( - namedOneOf( - "save", - "replicate", - "saveOrUpdate", - "update", - "merge", - "persist", - "lock", - "refresh", - "insert", - "delete", - // Lazy-load methods. - "immediateLoad", - "internalLoad")), - SessionInstrumentation.class.getName() + "$SessionMethodAdvice"); - - // Handle the non-generic 'get' separately. - transformers.put( - isMethod() - .and(named("get")) - .and(returns(named("java.lang.Object"))) - .and(takesArgument(0, named("java.lang.String"))), - SessionInstrumentation.class.getName() + "$SessionMethodAdvice"); - - // These methods return some object that we want to instrument, and so the Advice will pin the - // current Span to the returned object using a ContextStore. - transformers.put( - isMethod() - .and(namedOneOf("beginTransaction", "getTransaction")) - .and(returns(named("org.hibernate.Transaction"))), - SessionInstrumentation.class.getName() + "$GetTransactionAdvice"); - - transformers.put( - isMethod().and(returns(hasInterface(named("org.hibernate.Query")))), - SessionInstrumentation.class.getName() + "$GetQueryAdvice"); - - transformers.put( - isMethod().and(returns(hasInterface(named("org.hibernate.Criteria")))), - SessionInstrumentation.class.getName() + "$GetCriteriaAdvice"); - - return transformers; - } - - public static class SessionCloseAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void closeSession( - @Advice.This Object session, @Advice.Thrown Throwable throwable) { - - Context sessionContext = null; - if (session instanceof Session) { - ContextStore contextStore = - InstrumentationContext.get(Session.class, Context.class); - sessionContext = contextStore.get((Session) session); - } else if (session instanceof StatelessSession) { - ContextStore contextStore = - InstrumentationContext.get(StatelessSession.class, Context.class); - sessionContext = contextStore.get((StatelessSession) session); - } - - if (sessionContext == null) { - return; - } - Span sessionSpan = Java8BytecodeBridge.spanFromContext(sessionContext); - if (throwable != null) { - tracer().endExceptionally(sessionSpan, throwable); - } else { - tracer().end(sessionSpan); - } - } - } - - public static class SessionMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod( - @Advice.This Object session, - @Advice.Origin("#m") String name, - @Advice.Argument(0) Object entity) { - - boolean startSpan = !SCOPE_ONLY_METHODS.contains(name); - if (session instanceof Session) { - ContextStore contextStore = - InstrumentationContext.get(Session.class, Context.class); - return SessionMethodUtils.startScopeFrom( - contextStore, (Session) session, "Session." + name, entity, startSpan); - } else if (session instanceof StatelessSession) { - ContextStore contextStore = - InstrumentationContext.get(StatelessSession.class, Context.class); - return SessionMethodUtils.startScopeFrom( - contextStore, (StatelessSession) session, "Session." + name, entity, startSpan); - } - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Thrown Throwable throwable, - @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object returned, - @Advice.Origin("#m") String name) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, "Session." + name, returned); - } - } - - public static class GetQueryAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getQuery(@Advice.This Object session, @Advice.Return Query query) { - - ContextStore queryContextStore = - InstrumentationContext.get(Query.class, Context.class); - if (session instanceof Session) { - ContextStore sessionContextStore = - InstrumentationContext.get(Session.class, Context.class); - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, (Session) session, queryContextStore, query); - } else if (session instanceof StatelessSession) { - ContextStore sessionContextStore = - InstrumentationContext.get(StatelessSession.class, Context.class); - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, (StatelessSession) session, queryContextStore, query); - } - } - } - - public static class GetTransactionAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getTransaction( - @Advice.This Object session, @Advice.Return Transaction transaction) { - - ContextStore transactionContextStore = - InstrumentationContext.get(Transaction.class, Context.class); - - if (session instanceof Session) { - ContextStore sessionContextStore = - InstrumentationContext.get(Session.class, Context.class); - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, (Session) session, transactionContextStore, transaction); - } else if (session instanceof StatelessSession) { - ContextStore sessionContextStore = - InstrumentationContext.get(StatelessSession.class, Context.class); - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, (StatelessSession) session, transactionContextStore, transaction); - } - } - } - - public static class GetCriteriaAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getCriteria(@Advice.This Object session, @Advice.Return Criteria criteria) { - - ContextStore criteriaContextStore = - InstrumentationContext.get(Criteria.class, Context.class); - if (session instanceof Session) { - ContextStore sessionContextStore = - InstrumentationContext.get(Session.class, Context.class); - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, (Session) session, criteriaContextStore, criteria); - } else if (session instanceof StatelessSession) { - ContextStore sessionContextStore = - InstrumentationContext.get(StatelessSession.class, Context.class); - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, (StatelessSession) session, criteriaContextStore, criteria); - } - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java b/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java deleted file mode 100644 index d30cabe915..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/TransactionInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v3_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Transaction; - -public class TransactionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Transaction"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.Transaction")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("commit")).and(takesArguments(0)), - TransactionInstrumentation.class.getName() + "$TransactionCommitAdvice"); - } - - public static class TransactionCommitAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startCommit(@Advice.This Transaction transaction) { - - ContextStore contextStore = - InstrumentationContext.get(Transaction.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, transaction, "Transaction.commit", null, true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endCommit( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, null, null); - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/AbstractHibernateTest.groovy b/instrumentation/hibernate/hibernate-3.3/src/test/groovy/AbstractHibernateTest.groovy deleted file mode 100644 index 3a28d14fa8..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/AbstractHibernateTest.groovy +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.hibernate.Session -import org.hibernate.SessionFactory -import org.hibernate.cfg.AnnotationConfiguration -import spock.lang.Shared - -abstract class AbstractHibernateTest extends AgentTestRunner { - - @Shared - protected SessionFactory sessionFactory - - @Shared - protected List prepopulated - - def setupSpec() { - sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory() - - // Pre-populate the DB, so delete/update can be tested. - Session writer = sessionFactory.openSession() - writer.beginTransaction() - prepopulated = new ArrayList<>() - for (int i = 0; i < 2; i++) { - prepopulated.add(new Value("Hello :) " + i)) - writer.save(prepopulated.get(i)) - } - writer.getTransaction().commit() - writer.close() - } - - def cleanupSpec() { - if (sessionFactory != null) { - sessionFactory.close() - } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/CriteriaTest.groovy b/instrumentation/hibernate/hibernate-3.3/src/test/groovy/CriteriaTest.groovy deleted file mode 100644 index 4e546bef3f..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/CriteriaTest.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import org.hibernate.Criteria -import org.hibernate.Session -import org.hibernate.criterion.Order -import org.hibernate.criterion.Restrictions - -class CriteriaTest extends AbstractHibernateTest { - - def "test criteria.#methodName"() { - setup: - Session session = sessionFactory.openSession() - session.beginTransaction() - Criteria criteria = session.createCriteria(Value) - .add(Restrictions.like("name", "Hello")) - .addOrder(Order.desc("name")) - interaction.call(criteria) - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Criteria.$methodName" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - - where: - methodName | interaction - "list" | { c -> c.list() } - "uniqueResult" | { c -> c.uniqueResult() } - "scroll" | { c -> c.scroll() } - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/QueryTest.groovy b/instrumentation/hibernate/hibernate-3.3/src/test/groovy/QueryTest.groovy deleted file mode 100644 index 9c073aa167..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/QueryTest.groovy +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import org.hibernate.Query -import org.hibernate.Session - -class QueryTest extends AbstractHibernateTest { - - def "test hibernate query.#queryMethodName single call"() { - setup: - - // With Transaction - Session session = sessionFactory.openSession() - session.beginTransaction() - queryInteraction(session) - session.getTransaction().commit() - session.close() - - // Without Transaction - if (!requiresTransaction) { - session = sessionFactory.openSession() - queryInteraction(session) - session.close() - } - - expect: - assertTraces(requiresTransaction ? 1 : 2) { - // With Transaction - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name expectedSpanName - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - if (!requiresTransaction) { - // Without Transaction - trace(1, 3) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name expectedSpanName - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - } - } - - where: - queryMethodName | expectedSpanName | requiresTransaction | queryInteraction - "Query.list" | "from Value" | false | { sess -> - Query q = sess.createQuery("from Value") - q.list() - } - "Query.executeUpdate" | "update Value set name = ?" | true | { sess -> - Query q = sess.createQuery("update Value set name = ?") - q.setParameter(0, "alyx") - q.executeUpdate() - } - "Query.uniqueResult" | "from Value where id = ?" | false | { sess -> - Query q = sess.createQuery("from Value where id = ?") - q.setParameter(0, 1L) - q.uniqueResult() - } - "Query.iterate" | "from Value" | false | { sess -> - Query q = sess.createQuery("from Value") - q.iterate() - } - "Query.scroll" | "from Value" | false | { sess -> - Query q = sess.createQuery("from Value") - q.scroll() - } - } - - def "test hibernate query.iterate"() { - setup: - - Session session = sessionFactory.openSession() - session.beginTransaction() - Query q = session.createQuery("from Value") - Iterator it = q.iterate() - while (it.hasNext()) { - it.next() - } - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "from Value" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - } - -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/SessionTest.groovy b/instrumentation/hibernate/hibernate-3.3/src/test/groovy/SessionTest.groovy deleted file mode 100644 index 2f2080bd9f..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/test/groovy/SessionTest.groovy +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import org.hibernate.LockMode -import org.hibernate.MappingException -import org.hibernate.Query -import org.hibernate.ReplicationMode -import org.hibernate.Session -import spock.lang.Shared - -class SessionTest extends AbstractHibernateTest { - - @Shared - private Closure sessionBuilder = { return sessionFactory.openSession() } - @Shared - private Closure statelessSessionBuilder = { return sessionFactory.openStatelessSession() } - - - def "test hibernate action #testName"() { - setup: - - // Test for each implementation of Session. - for (def buildSession : sessionImplementations) { - def session = buildSession() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - } - - expect: - assertTraces(sessionImplementations.size()) { - for (int i = 0; i < sessionImplementations.size(); i++) { - trace(i, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - } - - where: - testName | methodName | resource | sessionImplementations | sessionMethodTest - "lock" | "lock" | "Value" | [sessionBuilder] | { sesh, val -> - sesh.lock(val, LockMode.READ) - } - "refresh" | "refresh" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val -> - sesh.refresh(val) - } - "get" | "get" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val -> - sesh.get("Value", val.getId()) - } - } - - def "test hibernate statless action #testName"() { - setup: - - // Test for each implementation of Session. - def session = statelessSessionBuilder() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(3) { - kind CLIENT - childOf span(2) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - } - - where: - testName | methodName | resource | sessionMethodTest - "insert" | "insert" | "Value" | { sesh, val -> - sesh.insert("Value", new Value("insert me")) - } - "update" | "update" | "Value" | { sesh, val -> - val.setName("New name") - sesh.update(val) - } - "update by entityName" | "update" | "Value" | { sesh, val -> - val.setName("New name") - sesh.update("Value", val) - } - "delete" | "delete" | "Value" | { sesh, val -> - sesh.delete(val) - } - } - - def "test hibernate replicate: #testName"() { - setup: - - // Test for each implementation of Session. - def session = sessionFactory.openSession() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 5) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(4) { - kind CLIENT - childOf span(3) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - - } - - where: - testName | methodName | resource | sessionMethodTest - "replicate" | "replicate" | "Value" | { sesh, val -> - Value replicated = new Value(val.getName() + " replicated") - replicated.setId(val.getId()) - sesh.replicate(replicated, ReplicationMode.OVERWRITE) - } - "replicate by entityName" | "replicate" | "Value" | { sesh, val -> - Value replicated = new Value(val.getName() + " replicated") - replicated.setId(val.getId()) - sesh.replicate("Value", replicated, ReplicationMode.OVERWRITE) - } - } - - def "test hibernate failed replicate"() { - setup: - - // Test for each implementation of Session. - def session = sessionFactory.openSession() - session.beginTransaction() - - try { - session.replicate(new Long(123) /* Not a valid entity */, ReplicationMode.OVERWRITE) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.replicate" - kind INTERNAL - childOf span(0) - errored(true) - errorEvent(MappingException, "Unknown entity: java.lang.Long") - } - span(2) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - - } - } - - - def "test hibernate commit action #testName"() { - setup: - - def session = sessionBuilder() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(3) { - kind CLIENT - childOf span(2) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - } - - where: - testName | methodName | resource | sessionMethodTest - "save" | "save" | "Value" | { sesh, val -> - sesh.save(new Value("Another value")) - } - "saveOrUpdate save" | "saveOrUpdate" | "Value" | { sesh, val -> - sesh.saveOrUpdate(new Value("Value")) - } - "saveOrUpdate update" | "saveOrUpdate" | "Value" | { sesh, val -> - val.setName("New name") - sesh.saveOrUpdate(val) - } - "merge" | "merge" | "Value" | { sesh, val -> - sesh.merge(new Value("merge me in")) - } - "persist" | "persist" | "Value" | { sesh, val -> - sesh.persist(new Value("merge me in")) - } - "update (Session)" | "update" | "Value" | { sesh, val -> - val.setName("New name") - sesh.update(val) - } - "update by entityName (Session)" | "update" | "Value" | { sesh, val -> - val.setName("New name") - sesh.update("Value", val) - } - "delete (Session)" | "delete" | "Value" | { sesh, val -> - sesh.delete(val) - } - } - - - def "test attaches State to query created via #queryMethodName"() { - setup: - Session session = sessionFactory.openSession() - session.beginTransaction() - Query query = queryBuildMethod(session) - query.list() - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name expectedSpanName - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - - where: - queryMethodName | expectedSpanName | queryBuildMethod - "createQuery" | "from Value" | { sess -> sess.createQuery("from Value") } - "getNamedQuery" | "from Value" | { sess -> sess.getNamedQuery("TestNamedQuery") } - "createSQLQuery" | "SELECT * FROM Value" | { sess -> sess.createSQLQuery("SELECT * FROM Value") } - } - - - def "test hibernate overlapping Sessions"() { - setup: - - runUnderTrace("overlapping Sessions") { - def session1 = sessionFactory.openSession() - session1.beginTransaction() - def session2 = sessionFactory.openStatelessSession() - def session3 = sessionFactory.openSession() - - def value1 = new Value("Value 1") - session1.save(value1) - session2.insert(new Value("Value 2")) - session3.save(new Value("Value 3")) - session1.delete(value1) - - session2.close() - session1.getTransaction().commit() - session1.close() - session3.close() - } - - expect: - assertTraces(1) { - trace(0, 11) { - span(0) { - name "overlapping Sessions" - attributes { - } - } - span(1) { - name "Session" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "Session.save Value" - kind INTERNAL - childOf span(1) - attributes { - } - } - span(3) { - name "Session.delete Value" - kind INTERNAL - childOf span(1) - attributes { - } - } - span(4) { - name "Transaction.commit" - kind INTERNAL - childOf span(1) - attributes { - } - } - span(5) { - name "INSERT db1.Value" - kind CLIENT - childOf span(4) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^insert / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(6) { - name "DELETE db1.Value" - kind CLIENT - childOf span(4) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^delete / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(7) { - name "Session" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(8) { - name "Session.insert Value" - kind INTERNAL - childOf span(7) - attributes { - } - } - span(9) { - name "Session" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(10) { - name "Session.save Value" - kind INTERNAL - childOf span(9) - attributes { - } - } - } - } - } -} - diff --git a/instrumentation/hibernate/hibernate-3.3/src/test/java/Value.java b/instrumentation/hibernate/hibernate-3.3/src/test/java/Value.java deleted file mode 100644 index d72b8d8a03..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/test/java/Value.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.NamedQuery; - -@Entity -@Table -@NamedQuery(name = "TestNamedQuery", query = "from Value") -public class Value { - - private Long id; - private String name; - - public Value() {} - - public Value(String name) { - this.name = name; - } - - @Id - @GeneratedValue(generator = "increment") - @GenericGenerator(name = "increment", strategy = "increment") - public Long getId() { - return id; - } - - private void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String title) { - name = title; - } -} diff --git a/instrumentation/hibernate/hibernate-3.3/src/test/resources/hibernate.cfg.xml b/instrumentation/hibernate/hibernate-3.3/src/test/resources/hibernate.cfg.xml deleted file mode 100644 index 39d96decbd..0000000000 --- a/instrumentation/hibernate/hibernate-3.3/src/test/resources/hibernate.cfg.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - false - - - org.h2.Driver - jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE - sa - - org.hibernate.dialect.H2Dialect - - 3 - org.hibernate.cache.internal.NoCacheProvider - true - - - create - - - - - - - diff --git a/instrumentation/hibernate/hibernate-4.0/hibernate-4.0.gradle b/instrumentation/hibernate/hibernate-4.0/hibernate-4.0.gradle deleted file mode 100644 index 1a02c5101b..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/hibernate-4.0.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.hibernate" - module = "hibernate-core" - versions = "[4.0.0.Final,)" - assertInverse = true - } -} - -dependencies { - library group: 'org.hibernate', name: 'hibernate-core', version: '4.0.0.Final' - - implementation project(':instrumentation:hibernate:hibernate-common') - - testImplementation project(':instrumentation:jdbc') - // Added to ensure cross compatibility: - testImplementation project(':instrumentation:hibernate:hibernate-3.3') - testImplementation project(':instrumentation:hibernate:hibernate-4.3') - - testImplementation group: 'com.h2database', name: 'h2', version: '1.4.197' - testImplementation "javax.xml.bind:jaxb-api:2.2.11" - testImplementation "com.sun.xml.bind:jaxb-core:2.2.11" - testImplementation "com.sun.xml.bind:jaxb-impl:2.2.11" - testImplementation "javax.activation:activation:1.1.1" - - latestDepTestLibrary group: 'org.hibernate', name: 'hibernate-core', version: '4.2.+' -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java deleted file mode 100644 index fe11341078..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/CriteriaInstrumentation.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Criteria; - -public class CriteriaInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Criteria"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.Criteria")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(namedOneOf("list", "uniqueResult", "scroll")), - CriteriaInstrumentation.class.getName() + "$CriteriaMethodAdvice"); - } - - public static class CriteriaMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod( - @Advice.This Criteria criteria, @Advice.Origin("#m") String name) { - - ContextStore contextStore = - InstrumentationContext.get(Criteria.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, criteria, "Criteria." + name, null, true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Thrown Throwable throwable, - @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object entity, - @Advice.Origin("#m") String name) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, "Criteria." + name, entity); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java deleted file mode 100644 index e1187079ec..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class HibernateInstrumentationModule extends InstrumentationModule { - - public HibernateInstrumentationModule() { - super("hibernate", "hibernate-4.0"); - } - - @Override - public List typeInstrumentations() { - return asList( - new CriteriaInstrumentation(), - new QueryInstrumentation(), - new SessionFactoryInstrumentation(), - new SessionInstrumentation(), - new TransactionInstrumentation()); - } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.Criteria", Context.class.getName()); - map.put("org.hibernate.Query", Context.class.getName()); - map.put("org.hibernate.SharedSessionContract", Context.class.getName()); - map.put("org.hibernate.Transaction", Context.class.getName()); - return Collections.unmodifiableMap(map); - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java deleted file mode 100644 index 4250c05ea1..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/QueryInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Query; - -public class QueryInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Query"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.Query")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(namedOneOf("list", "executeUpdate", "uniqueResult", "iterate", "scroll")), - QueryInstrumentation.class.getName() + "$QueryMethodAdvice"); - } - - public static class QueryMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod(@Advice.This Query query) { - - ContextStore contextStore = - InstrumentationContext.get(Query.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, query, query.getQueryString(), null, true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, null, null); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java deleted file mode 100644 index cf612dee1c..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionFactoryInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.SharedSessionContract; - -public class SessionFactoryInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.SessionFactory"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.SessionFactory")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(namedOneOf("openSession", "openStatelessSession")) - .and(takesArguments(0)) - .and(returns(namedOneOf("org.hibernate.Session", "org.hibernate.StatelessSession"))), - SessionFactoryInstrumentation.class.getName() + "$SessionFactoryAdvice"); - } - - public static class SessionFactoryAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void openSession(@Advice.Return SharedSessionContract session) { - - Context context = Java8BytecodeBridge.currentContext(); - Span span = tracer().startSpan(context, "Session"); - - ContextStore contextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - contextStore.putIfAbsent(session, context.with(span)); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java deleted file mode 100644 index bc35a87095..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/SessionInstrumentation.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils.SCOPE_ONLY_METHODS; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Criteria; -import org.hibernate.Query; -import org.hibernate.SharedSessionContract; -import org.hibernate.Transaction; - -public class SessionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.SharedSessionContract"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.SharedSessionContract")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(named("close")).and(takesArguments(0)), - SessionInstrumentation.class.getName() + "$SessionCloseAdvice"); - - // Session synchronous methods we want to instrument. - transformers.put( - isMethod() - .and( - namedOneOf( - "save", - "replicate", - "saveOrUpdate", - "update", - "merge", - "persist", - "lock", - "refresh", - "insert", - "delete", - // Lazy-load methods. - "immediateLoad", - "internalLoad")), - SessionInstrumentation.class.getName() + "$SessionMethodAdvice"); - // Handle the non-generic 'get' separately. - transformers.put( - isMethod() - .and(named("get")) - .and(returns(named("java.lang.Object"))) - .and(takesArgument(0, named("java.lang.String"))), - SessionInstrumentation.class.getName() + "$SessionMethodAdvice"); - - // These methods return some object that we want to instrument, and so the Advice will pin the - // current Span to the returned object using a ContextStore. - transformers.put( - isMethod() - .and(namedOneOf("beginTransaction", "getTransaction")) - .and(returns(named("org.hibernate.Transaction"))), - SessionInstrumentation.class.getName() + "$GetTransactionAdvice"); - - transformers.put( - isMethod().and(returns(hasInterface(named("org.hibernate.Query")))), - SessionInstrumentation.class.getName() + "$GetQueryAdvice"); - - transformers.put( - isMethod().and(returns(hasInterface(named("org.hibernate.Criteria")))), - SessionInstrumentation.class.getName() + "$GetCriteriaAdvice"); - - return transformers; - } - - public static class SessionCloseAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void closeSession( - @Advice.This SharedSessionContract session, @Advice.Thrown Throwable throwable) { - - ContextStore contextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - Context sessionContext = contextStore.get(session); - if (sessionContext == null) { - return; - } - Span sessionSpan = Java8BytecodeBridge.spanFromContext(sessionContext); - if (throwable != null) { - tracer().endExceptionally(sessionSpan, throwable); - } else { - tracer().end(sessionSpan); - } - } - } - - public static class SessionMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod( - @Advice.This SharedSessionContract session, - @Advice.Origin("#m") String name, - @Advice.Argument(0) Object entity) { - - boolean startSpan = !SCOPE_ONLY_METHODS.contains(name); - ContextStore contextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - return SessionMethodUtils.startScopeFrom( - contextStore, session, "Session." + name, entity, startSpan); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Thrown Throwable throwable, - @Advice.Return(typing = Assigner.Typing.DYNAMIC) Object returned, - @Advice.Origin("#m") String name) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, "Session." + name, returned); - } - } - - public static class GetQueryAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getQuery( - @Advice.This SharedSessionContract session, @Advice.Return Query query) { - - ContextStore sessionContextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - ContextStore queryContextStore = - InstrumentationContext.get(Query.class, Context.class); - - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, session, queryContextStore, query); - } - } - - public static class GetTransactionAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getTransaction( - @Advice.This SharedSessionContract session, @Advice.Return Transaction transaction) { - - ContextStore sessionContextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - ContextStore transactionContextStore = - InstrumentationContext.get(Transaction.class, Context.class); - - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, session, transactionContextStore, transaction); - } - } - - public static class GetCriteriaAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getCriteria( - @Advice.This SharedSessionContract session, @Advice.Return Criteria criteria) { - - ContextStore sessionContextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - ContextStore criteriaContextStore = - InstrumentationContext.get(Criteria.class, Context.class); - - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, session, criteriaContextStore, criteria); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java b/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java deleted file mode 100644 index f126d782a9..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/TransactionInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.Transaction; - -public class TransactionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.Transaction"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.Transaction")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("commit")).and(takesArguments(0)), - TransactionInstrumentation.class.getName() + "$TransactionCommitAdvice"); - } - - public static class TransactionCommitAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startCommit(@Advice.This Transaction transaction) { - - ContextStore contextStore = - InstrumentationContext.get(Transaction.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, transaction, "Transaction.commit", null, true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endCommit( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - - SessionMethodUtils.closeScope(spanWithScope, throwable, null, null); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/AbstractHibernateTest.groovy b/instrumentation/hibernate/hibernate-4.0/src/test/groovy/AbstractHibernateTest.groovy deleted file mode 100644 index d724138784..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/AbstractHibernateTest.groovy +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.hibernate.Session -import org.hibernate.SessionFactory -import org.hibernate.cfg.Configuration -import spock.lang.Shared - -abstract class AbstractHibernateTest extends AgentTestRunner { - - @Shared - protected SessionFactory sessionFactory - - @Shared - protected List prepopulated - - def setupSpec() { - sessionFactory = new Configuration().configure().buildSessionFactory() - // Pre-populate the DB, so delete/update can be tested. - Session writer = sessionFactory.openSession() - writer.beginTransaction() - prepopulated = new ArrayList<>() - for (int i = 0; i < 2; i++) { - prepopulated.add(new Value("Hello :) " + i)) - writer.save(prepopulated.get(i)) - } - writer.getTransaction().commit() - writer.close() - } - - def cleanupSpec() { - if (sessionFactory != null) { - sessionFactory.close() - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/CriteriaTest.groovy b/instrumentation/hibernate/hibernate-4.0/src/test/groovy/CriteriaTest.groovy deleted file mode 100644 index 4e546bef3f..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/CriteriaTest.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import org.hibernate.Criteria -import org.hibernate.Session -import org.hibernate.criterion.Order -import org.hibernate.criterion.Restrictions - -class CriteriaTest extends AbstractHibernateTest { - - def "test criteria.#methodName"() { - setup: - Session session = sessionFactory.openSession() - session.beginTransaction() - Criteria criteria = session.createCriteria(Value) - .add(Restrictions.like("name", "Hello")) - .addOrder(Order.desc("name")) - interaction.call(criteria) - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Criteria.$methodName" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - - where: - methodName | interaction - "list" | { c -> c.list() } - "uniqueResult" | { c -> c.uniqueResult() } - "scroll" | { c -> c.scroll() } - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/QueryTest.groovy b/instrumentation/hibernate/hibernate-4.0/src/test/groovy/QueryTest.groovy deleted file mode 100644 index 00ebb5f5bd..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/QueryTest.groovy +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import org.hibernate.Query -import org.hibernate.Session - -class QueryTest extends AbstractHibernateTest { - - def "test hibernate query.#queryMethodName single call"() { - setup: - - // With Transaction - Session session = sessionFactory.openSession() - session.beginTransaction() - queryInteraction(session) - session.getTransaction().commit() - session.close() - - // Without Transaction - if (!requiresTransaction) { - session = sessionFactory.openSession() - queryInteraction(session) - session.close() - } - - expect: - assertTraces(requiresTransaction ? 1 : 2) { - // With Transaction - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name expectedSpanName - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - if (!requiresTransaction) { - // Without Transaction - trace(1, 3) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name expectedSpanName - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - } - } - - where: - queryMethodName | expectedSpanName | requiresTransaction | queryInteraction - "query/list" | "from Value" | false | { sess -> - Query q = sess.createQuery("from Value") - q.list() - } - "query/executeUpdate" | "update Value set name = ?" | true | { sess -> - Query q = sess.createQuery("update Value set name = ?") - q.setParameter(0, "alyx") - q.executeUpdate() - } - "query/uniqueResult" | "from Value where id = ?" | false | { sess -> - Query q = sess.createQuery("from Value where id = ?") - q.setParameter(0, 1L) - q.uniqueResult() - } - "iterate" | "from Value" | false | { sess -> - Query q = sess.createQuery("from Value") - q.iterate() - } - "query/scroll" | "from Value" | false | { sess -> - Query q = sess.createQuery("from Value") - q.scroll() - } - } - - def "test hibernate query.iterate"() { - setup: - - Session session = sessionFactory.openSession() - session.beginTransaction() - Query q = session.createQuery("from Value") - Iterator it = q.iterate() - while (it.hasNext()) { - it.next() - } - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "from Value" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - } - -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/SessionTest.groovy b/instrumentation/hibernate/hibernate-4.0/src/test/groovy/SessionTest.groovy deleted file mode 100644 index 2ede063d83..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/test/groovy/SessionTest.groovy +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import org.hibernate.LockMode -import org.hibernate.MappingException -import org.hibernate.Query -import org.hibernate.ReplicationMode -import org.hibernate.Session -import spock.lang.Shared - -class SessionTest extends AbstractHibernateTest { - - @Shared - private Closure sessionBuilder = { return sessionFactory.openSession() } - @Shared - private Closure statelessSessionBuilder = { return sessionFactory.openStatelessSession() } - - - def "test hibernate action #testName"() { - setup: - - // Test for each implementation of Session. - for (def buildSession : sessionImplementations) { - def session = buildSession() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - } - - expect: - assertTraces(sessionImplementations.size()) { - for (int i = 0; i < sessionImplementations.size(); i++) { - trace(i, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - childOf span(1) - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - } - - where: - testName | methodName | resource | sessionImplementations | sessionMethodTest - "lock" | "lock" | "Value" | [sessionBuilder] | { sesh, val -> - sesh.lock(val, LockMode.READ) - } - "refresh" | "refresh" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val -> - sesh.refresh(val) - } - "get" | "get" | "Value" | [sessionBuilder, statelessSessionBuilder] | { sesh, val -> - sesh.get("Value", val.getId()) - } - "insert" | "insert" | "Value" | [statelessSessionBuilder] | { sesh, val -> - sesh.insert("Value", new Value("insert me")) - } - "update (StatelessSession)" | "update" | "Value" | [statelessSessionBuilder] | { sesh, val -> - val.setName("New name") - sesh.update(val) - } - "update by entityName (StatelessSession)" | "update" | "Value" | [statelessSessionBuilder] | { sesh, val -> - val.setName("New name") - sesh.update("Value", val) - } - "delete (Session)" | "delete" | "Value" | [statelessSessionBuilder] | { sesh, val -> - sesh.delete(val) - } - } - - def "test hibernate replicate: #testName"() { - setup: - - // Test for each implementation of Session. - def session = sessionFactory.openSession() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 5) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "SELECT db1.Value" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^select / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(4) { - kind CLIENT - childOf span(3) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - - } - - where: - testName | methodName | resource | sessionMethodTest - "replicate" | "replicate" | "Value" | { sesh, val -> - Value replicated = new Value(val.getName() + " replicated") - replicated.setId(val.getId()) - sesh.replicate(replicated, ReplicationMode.OVERWRITE) - } - "replicate by entityName" | "replicate" | "Value" | { sesh, val -> - Value replicated = new Value(val.getName() + " replicated") - replicated.setId(val.getId()) - sesh.replicate("Value", replicated, ReplicationMode.OVERWRITE) - } - } - - def "test hibernate failed replicate"() { - setup: - - // Test for each implementation of Session. - def session = sessionFactory.openSession() - session.beginTransaction() - - try { - session.replicate(new Long(123) /* Not a valid entity */, ReplicationMode.OVERWRITE) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.replicate" - kind INTERNAL - childOf span(0) - errored(true) - errorEvent(MappingException, "Unknown entity: java.lang.Long") - } - span(2) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - - } - } - - - def "test hibernate commit action #testName"() { - setup: - - def session = sessionBuilder() - session.beginTransaction() - - try { - sessionMethodTest.call(session, prepopulated.get(0)) - } catch (Exception e) { - // We expected this, we should see the error field set on the span. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "Session.$methodName $resource" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(3) { - kind CLIENT - childOf span(2) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - } - } - - where: - testName | methodName | resource | sessionMethodTest - "save" | "save" | "Value" | { sesh, val -> - sesh.save(new Value("Another value")) - } - "saveOrUpdate save" | "saveOrUpdate" | "Value" | { sesh, val -> - sesh.saveOrUpdate(new Value("Value")) - } - "saveOrUpdate update" | "saveOrUpdate" | "Value" | { sesh, val -> - val.setName("New name") - sesh.saveOrUpdate(val) - } - "merge" | "merge" | "Value" | { sesh, val -> - sesh.merge(new Value("merge me in")) - } - "persist" | "persist" | "Value" | { sesh, val -> - sesh.persist(new Value("merge me in")) - } - "update (Session)" | "update" | "Value" | { sesh, val -> - val.setName("New name") - sesh.update(val) - } - "update by entityName (Session)" | "update" | "Value" | { sesh, val -> - val.setName("New name") - sesh.update("Value", val) - } - "delete (Session)" | "delete" | "Value" | { sesh, val -> - sesh.delete(val) - } - } - - - def "test attaches State to query created via #queryMethodName"() { - setup: - Session session = sessionFactory.openSession() - session.beginTransaction() - Query query = queryBuildMethod(session) - query.list() - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name resource - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" String - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(3) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - - where: - queryMethodName | resource | queryBuildMethod - "createQuery" | "from Value" | { sess -> sess.createQuery("from Value") } - "getNamedQuery" | "from Value" | { sess -> sess.getNamedQuery("TestNamedQuery") } - "createSQLQuery" | "SELECT * FROM Value" | { sess -> sess.createSQLQuery("SELECT * FROM Value") } - } - - - def "test hibernate overlapping Sessions"() { - setup: - - runUnderTrace("overlapping Sessions") { - def session1 = sessionFactory.openSession() - session1.beginTransaction() - def session2 = sessionFactory.openStatelessSession() - def session3 = sessionFactory.openSession() - - def value1 = new Value("Value 1") - session1.save(value1) - session2.insert(new Value("Value 2")) - session3.save(new Value("Value 3")) - session1.delete(value1) - - session2.close() - session1.getTransaction().commit() - session1.close() - session3.close() - } - - expect: - assertTraces(1) { - trace(0, 12) { - span(0) { - name "overlapping Sessions" - attributes { - } - } - span(1) { - name "Session" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "Session.save Value" - kind INTERNAL - childOf span(1) - attributes { - } - } - span(3) { - name "Session.delete Value" - kind INTERNAL - childOf span(1) - attributes { - } - } - span(4) { - name "Transaction.commit" - kind INTERNAL - childOf span(1) - attributes { - } - } - span(5) { - name "INSERT db1.Value" - kind CLIENT - childOf span(4) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^insert / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(6) { - name "DELETE db1.Value" - kind CLIENT - childOf span(4) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^delete / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(7) { - name "Session" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(8) { - name "Session.insert Value" - kind INTERNAL - childOf span(7) - attributes { - } - } - span(9) { - name "INSERT db1.Value" - kind CLIENT - childOf span(8) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "h2" - "${SemanticAttributes.DB_NAME.key()}" "db1" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/^insert / - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "h2:mem:" - } - } - span(10) { - name "Session" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(11) { - name "Session.save Value" - kind INTERNAL - childOf span(10) - attributes { - } - } - } - } - } -} - diff --git a/instrumentation/hibernate/hibernate-4.0/src/test/java/Value.java b/instrumentation/hibernate/hibernate-4.0/src/test/java/Value.java deleted file mode 100644 index d72b8d8a03..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/test/java/Value.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.NamedQuery; - -@Entity -@Table -@NamedQuery(name = "TestNamedQuery", query = "from Value") -public class Value { - - private Long id; - private String name; - - public Value() {} - - public Value(String name) { - this.name = name; - } - - @Id - @GeneratedValue(generator = "increment") - @GenericGenerator(name = "increment", strategy = "increment") - public Long getId() { - return id; - } - - private void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String title) { - name = title; - } -} diff --git a/instrumentation/hibernate/hibernate-4.0/src/test/resources/hibernate.cfg.xml b/instrumentation/hibernate/hibernate-4.0/src/test/resources/hibernate.cfg.xml deleted file mode 100644 index 511c3e8288..0000000000 --- a/instrumentation/hibernate/hibernate-4.0/src/test/resources/hibernate.cfg.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - org.h2.Driver - jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE - sa - - org.hibernate.dialect.H2Dialect - - 3 - org.hibernate.cache.internal.NoCacheProvider - true - - - create - - - - - - - diff --git a/instrumentation/hibernate/hibernate-4.3/hibernate-4.3.gradle b/instrumentation/hibernate/hibernate-4.3/hibernate-4.3.gradle deleted file mode 100644 index 3faef9c327..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/hibernate-4.3.gradle +++ /dev/null @@ -1,33 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.hibernate" - module = "hibernate-core" - versions = "[4.3.0.Final,)" - assertInverse = true - } -} - -dependencies { - library group: 'org.hibernate', name: 'hibernate-core', version: '4.3.0.Final' - - implementation project(':instrumentation:hibernate:hibernate-common') - - testImplementation project(':instrumentation:jdbc') - // Added to ensure cross compatibility: - testImplementation project(':instrumentation:hibernate:hibernate-3.3') - testImplementation project(':instrumentation:hibernate:hibernate-4.0') - - testLibrary group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.3.0.Final' - testImplementation group: 'org.hsqldb', name: 'hsqldb', version: '2.0.0' - //First version to work with Java 14 - testLibrary group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.8.0.RELEASE' - - // TODO(anuraaga): Investigate why these tests don't pass on 5 or 6 - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1042 - latestDepTestLibrary group: 'org.hibernate', name: 'hibernate-core', version: '4.+' - latestDepTestLibrary group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.+' - - latestDepTestLibrary group: 'org.springframework.data', name: 'spring-data-jpa', version: '(,2.4.0)' -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java deleted file mode 100644 index b1d0003523..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_3; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class HibernateInstrumentationModule extends InstrumentationModule { - public HibernateInstrumentationModule() { - super("hibernate", "hibernate-4.3"); - } - - @Override - public List typeInstrumentations() { - return asList(new ProcedureCallInstrumentation(), new SessionInstrumentation()); - } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.SharedSessionContract", Context.class.getName()); - map.put("org.hibernate.procedure.ProcedureCall", Context.class.getName()); - return Collections.unmodifiableMap(map); - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java deleted file mode 100644 index 5c105f8cf5..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/ProcedureCallInstrumentation.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.procedure.ProcedureCall; - -public class ProcedureCallInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.procedure.ProcedureCall"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.procedure.ProcedureCall")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("getOutputs")), - ProcedureCallInstrumentation.class.getName() + "$ProcedureCallMethodAdvice"); - } - - public static class ProcedureCallMethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope startMethod( - @Advice.This ProcedureCall call, @Advice.Origin("#m") String name) { - - ContextStore contextStore = - InstrumentationContext.get(ProcedureCall.class, Context.class); - - return SessionMethodUtils.startScopeFrom( - contextStore, call, "ProcedureCall." + name, call.getProcedureName(), true); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void endMethod( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - SessionMethodUtils.closeScope(spanWithScope, throwable, null, null); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java b/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java deleted file mode 100644 index 86308fa864..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/SessionInstrumentation.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate.v4_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.hibernate.SessionMethodUtils; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.hibernate.SharedSessionContract; -import org.hibernate.procedure.ProcedureCall; - -public class SessionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.hibernate.SharedSessionContract"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.hibernate.SharedSessionContract")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(returns(hasInterface(named("org.hibernate.procedure.ProcedureCall")))), - SessionInstrumentation.class.getName() + "$GetProcedureCallAdvice"); - } - - public static class GetProcedureCallAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void getProcedureCall( - @Advice.This SharedSessionContract session, @Advice.Return ProcedureCall returned) { - - ContextStore sessionContextStore = - InstrumentationContext.get(SharedSessionContract.class, Context.class); - ContextStore returnedContextStore = - InstrumentationContext.get(ProcedureCall.class, Context.class); - - SessionMethodUtils.attachSpanFromStore( - sessionContextStore, session, returnedContextStore, returned); - } - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/groovy/ProcedureCallTest.groovy b/instrumentation/hibernate/hibernate-4.3/src/test/groovy/ProcedureCallTest.groovy deleted file mode 100644 index 4244f463ac..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/groovy/ProcedureCallTest.groovy +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.sql.Connection -import java.sql.DriverManager -import java.sql.Statement -import javax.persistence.ParameterMode -import org.hibernate.Session -import org.hibernate.SessionFactory -import org.hibernate.cfg.Configuration -import org.hibernate.exception.SQLGrammarException -import org.hibernate.procedure.ProcedureCall -import spock.lang.Shared - -class ProcedureCallTest extends AgentTestRunner { - - - @Shared - protected SessionFactory sessionFactory - - @Shared - protected List prepopulated - - def setupSpec() { - sessionFactory = new Configuration().configure().buildSessionFactory() - // Pre-populate the DB, so delete/update can be tested. - Session writer = sessionFactory.openSession() - writer.beginTransaction() - prepopulated = new ArrayList<>() - for (int i = 0; i < 2; i++) { - prepopulated.add(new Value("Hello :) " + i)) - writer.save(prepopulated.get(i)) - } - writer.getTransaction().commit() - writer.close() - - // Create a stored procedure. - Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:test", "sa", "1") - Statement stmt = conn.createStatement() - stmt.execute("CREATE PROCEDURE TEST_PROC() MODIFIES SQL DATA BEGIN ATOMIC INSERT INTO Value VALUES (420, 'fred'); END") - stmt.close() - conn.close() - } - - def cleanupSpec() { - if (sessionFactory != null) { - sessionFactory.close() - } - } - - def "test ProcedureCall"() { - setup: - - Session session = sessionFactory.openSession() - session.beginTransaction() - - ProcedureCall call = session.createStoredProcedureCall("TEST_PROC") - call.getOutputs() - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "ProcedureCall.getOutputs TEST_PROC" - kind INTERNAL - childOf span(0) - attributes { - } - } - span(2) { - name "test" - kind CLIENT - childOf span(1) - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "{call TEST_PROC()}" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - span(3) { - kind INTERNAL - name "Transaction.commit" - childOf span(0) - attributes { - } - } - } - } - } - - def "test failing ProcedureCall"() { - setup: - - Session session = sessionFactory.openSession() - session.beginTransaction() - - ProcedureCall call = session.createStoredProcedureCall("TEST_PROC") - call.registerParameter("nonexistent", Long, ParameterMode.IN) - call.getParameterRegistration("nonexistent").bindValue(420L) - try { - call.getOutputs() - } catch (Exception e) { - // We expected this. - } - - session.getTransaction().commit() - session.close() - - expect: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "Session" - kind INTERNAL - hasNoParent() - attributes { - } - } - span(1) { - name "ProcedureCall.getOutputs TEST_PROC" - kind INTERNAL - childOf span(0) - errored(true) - errorEvent(SQLGrammarException, "could not prepare statement") - } - span(2) { - name "Transaction.commit" - kind INTERNAL - childOf span(0) - attributes { - } - } - } - } - } -} - diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/groovy/SpringJpaTest.groovy b/instrumentation/hibernate/hibernate-4.3/src/test/groovy/SpringJpaTest.groovy deleted file mode 100644 index ed02e7427a..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/groovy/SpringJpaTest.groovy +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import spock.lang.Shared -import spring.jpa.Customer -import spring.jpa.CustomerRepository -import spring.jpa.PersistenceConfig - -/** - * Unfortunately this test verifies that our hibernate instrumentation doesn't currently work with Spring Data Repositories. - */ -class SpringJpaTest extends AgentTestRunner { - - @Shared - def context = new AnnotationConfigApplicationContext(PersistenceConfig) - - @Shared - def repo = context.getBean(CustomerRepository) - - def "test CRUD"() { - setup: - def customer = new Customer("Bob", "Anonymous") - - expect: - customer.id == null - !repo.findAll().iterator().hasNext() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SELECT test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "select customer0_.id as id1_0_, customer0_.firstName as firstNam2_0_, customer0_.lastName as lastName3_0_ from Customer customer0_" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - } - TEST_WRITER.clear() - - when: - repo.save(customer) - def savedId = customer.id - - then: - customer.id != null - // Behavior changed in new version: - def extraTrace = TEST_WRITER.traces.size() == 2 - assertTraces(extraTrace ? 2 : 1) { - if (extraTrace) { - trace(0, 1) { - span(0) { - name "test" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "call next value for hibernate_sequence" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - } - trace(extraTrace ? 1 : 0, 1) { - span(0) { - name "INSERT test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" ~/insert into Customer \(.*\) values \(.*, \?, \?\)/ - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - } - TEST_WRITER.clear() - - when: - customer.firstName = "Bill" - repo.save(customer) - - then: - customer.id == savedId - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SELECT test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "select customer0_.id as id1_0_0_, customer0_.firstName as firstNam2_0_0_, customer0_.lastName as lastName3_0_0_ from Customer customer0_ where customer0_.id=?" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - trace(1, 1) { - span(0) { - name "UPDATE test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "update Customer set firstName=?, lastName=? where id=?" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - } - TEST_WRITER.clear() - - when: - customer = repo.findByLastName("Anonymous")[0] - - then: - customer.id == savedId - customer.firstName == "Bill" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SELECT test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "select customer0_.id as id1_0_, customer0_.firstName as firstNam2_0_, customer0_.lastName as lastName3_0_ from Customer customer0_ where customer0_.lastName=?" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - } - TEST_WRITER.clear() - - when: - repo.delete(customer) - - then: - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SELECT test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "select customer0_.id as id1_0_0_, customer0_.firstName as firstNam2_0_0_, customer0_.lastName as lastName3_0_0_ from Customer customer0_ where customer0_.id=?" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - trace(1, 1) { - span(0) { - name "DELETE test.Customer" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "hsqldb" - "${SemanticAttributes.DB_NAME.key()}" "test" - "${SemanticAttributes.DB_USER.key()}" "sa" - "${SemanticAttributes.DB_STATEMENT.key()}" "delete from Customer where id=?" - "${SemanticAttributes.DB_CONNECTION_STRING.key()}" "hsqldb:mem:" - } - } - } - } - TEST_WRITER.clear() - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/java/Value.java b/instrumentation/hibernate/hibernate-4.3/src/test/java/Value.java deleted file mode 100644 index d72b8d8a03..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/java/Value.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Table; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.NamedQuery; - -@Entity -@Table -@NamedQuery(name = "TestNamedQuery", query = "from Value") -public class Value { - - private Long id; - private String name; - - public Value() {} - - public Value(String name) { - this.name = name; - } - - @Id - @GeneratedValue(generator = "increment") - @GenericGenerator(name = "increment", strategy = "increment") - public Long getId() { - return id; - } - - private void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String title) { - name = title; - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/Customer.java b/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/Customer.java deleted file mode 100644 index 27e7d68940..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/Customer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package spring.jpa; - -import java.util.Objects; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -@Entity -public class Customer { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String firstName; - private String lastName; - - protected Customer() {} - - public Customer(String firstName, String lastName) { - this.firstName = firstName; - this.lastName = lastName; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - @Override - public String toString() { - return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Customer)) { - return false; - } - Customer other = (Customer) obj; - return Objects.equals(id, other.id) - && Objects.equals(firstName, other.firstName) - && Objects.equals(lastName, other.lastName); - } - - @Override - public int hashCode() { - return Objects.hash(id, firstName, lastName); - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/CustomerRepository.java b/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/CustomerRepository.java deleted file mode 100644 index 9662f2a4b5..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/CustomerRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package spring.jpa; - -import java.util.List; -import org.springframework.data.repository.CrudRepository; - -public interface CustomerRepository extends CrudRepository { - - List findByLastName(String lastName); -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/PersistenceConfig.java b/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/PersistenceConfig.java deleted file mode 100644 index 98afef6b75..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/java/spring/jpa/PersistenceConfig.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package spring.jpa; - -import java.util.Properties; -import javax.sql.DataSource; -import org.springframework.context.annotation.Bean; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.Database; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.transaction.PlatformTransactionManager; - -@EnableJpaRepositories(basePackages = "spring/jpa") -public class PersistenceConfig { - - @Bean(name = "transactionManager") - public PlatformTransactionManager dbTransactionManager() { - JpaTransactionManager transactionManager = new JpaTransactionManager(); - transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); - return transactionManager; - } - - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - - HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - vendorAdapter.setDatabase(Database.HSQL); - vendorAdapter.setGenerateDdl(true); - - LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); - em.setDataSource(dataSource()); - em.setPackagesToScan("spring/jpa"); - em.setJpaVendorAdapter(vendorAdapter); - em.setJpaProperties(additionalProperties()); - - return em; - } - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); - dataSource.setUrl("jdbc:hsqldb:mem:test"); - dataSource.setUsername("sa"); - dataSource.setPassword("1"); - return dataSource; - } - - private Properties additionalProperties() { - Properties properties = new Properties(); - properties.setProperty("hibernate.show_sql", "true"); - properties.setProperty("hibernate.hbm2ddl.auto", "create"); - properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); - // properties.setProperty( - // "hibernate.format_sql", - // env.getProperty("spring.jpa.properties.hibernate.format_sql")); - return properties; - } -} diff --git a/instrumentation/hibernate/hibernate-4.3/src/test/resources/hibernate.cfg.xml b/instrumentation/hibernate/hibernate-4.3/src/test/resources/hibernate.cfg.xml deleted file mode 100644 index dc2c557770..0000000000 --- a/instrumentation/hibernate/hibernate-4.3/src/test/resources/hibernate.cfg.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - class,hbm - org.hibernate.dialect.HSQLDialect - true - org.hsqldb.jdbcDriver - sa - 1 - jdbc:hsqldb:mem:test - create - - - - - - - diff --git a/instrumentation/hibernate/hibernate-common/hibernate-common.gradle b/instrumentation/hibernate/hibernate-common/hibernate-common.gradle deleted file mode 100644 index dba9283db5..0000000000 --- a/instrumentation/hibernate/hibernate-common/hibernate-common.gradle +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Classes that are common to all versions of the Hibernate instrumentation. - */ - -apply from: "$rootDir/gradle/instrumentation.gradle" diff --git a/instrumentation/hibernate/hibernate-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateTracer.java b/instrumentation/hibernate/hibernate-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateTracer.java deleted file mode 100644 index 41e60e042d..0000000000 --- a/instrumentation/hibernate/hibernate-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateTracer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.lang.annotation.Annotation; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class HibernateTracer extends BaseTracer { - private static final HibernateTracer TRACER = new HibernateTracer(); - - public static HibernateTracer tracer() { - return TRACER; - } - - public Span startSpan(Context context, String operationName, Object entity) { - return startSpan(context, spanNameForOperation(operationName, entity)); - } - - public Span startSpan(Context context, String spanName) { - return tracer.spanBuilder(spanName).setParent(context).startSpan(); - } - - private String spanNameForOperation(String operationName, Object entity) { - if (entity != null) { - String entityName = entityName(entity); - if (entityName != null) { - return operationName + " " + entityName; - } - } - return operationName; - } - - String entityName(Object entity) { - if (entity == null) { - return null; - } - String name = null; - Set annotations = new HashSet<>(); - for (Annotation annotation : entity.getClass().getDeclaredAnnotations()) { - annotations.add(annotation.annotationType().getName()); - } - - if (entity instanceof String) { - // We were given an entity name, not the entity itself. - name = (String) entity; - } else if (annotations.contains("javax.persistence.Entity")) { - // We were given an instance of an entity. - name = entity.getClass().getName(); - } else if (entity instanceof List && !((List) entity).isEmpty()) { - // We have a list of entities. - name = entityName(((List) entity).get(0)); - } - - return name; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.hibernate"; - } -} diff --git a/instrumentation/hibernate/hibernate-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/SessionMethodUtils.java b/instrumentation/hibernate/hibernate-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/SessionMethodUtils.java deleted file mode 100644 index 9dfb137fbf..0000000000 --- a/instrumentation/hibernate/hibernate-common/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/SessionMethodUtils.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hibernate; - -import static io.opentelemetry.javaagent.instrumentation.hibernate.HibernateTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -public class SessionMethodUtils { - - public static final Set SCOPE_ONLY_METHODS = - new HashSet<>(Arrays.asList("immediateLoad", "internalLoad")); - - // Starts a scope as a child from a Span, where the Span is attached to the given spanKey using - // the given contextStore. - public static SpanWithScope startScopeFrom( - ContextStore contextStore, - TARGET spanKey, - String operationName, - ENTITY entity, - boolean createSpan) { - - Context sessionContext = contextStore.get(spanKey); - if (sessionContext == null) { - return null; // No state found. We aren't in a Session. - } - - int depth = CallDepthThreadLocalMap.incrementCallDepth(SessionMethodUtils.class); - if (depth > 0) { - return null; // This method call is being traced already. - } - - if (createSpan) { - Span span = tracer().startSpan(sessionContext, operationName, entity); - return new SpanWithScope(span, sessionContext.with(span).makeCurrent()); - } else { - return new SpanWithScope(null, sessionContext.makeCurrent()); - } - } - - // Closes a Scope/Span, adding an error tag if the given Throwable is not null. - public static void closeScope( - SpanWithScope spanWithScope, Throwable throwable, String operationName, Object entity) { - - if (spanWithScope == null) { - // This method call was re-entrant. Do nothing, since it is being traced by the parent/first - // call. - return; - } - CallDepthThreadLocalMap.reset(SessionMethodUtils.class); - - Span span = spanWithScope.getSpan(); - if (span != null) { - if (operationName != null && entity != null) { - String entityName = tracer().entityName(entity); - if (entityName != null) { - span.updateName(operationName + " " + entityName); - } - } - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - spanWithScope.closeScope(); - } - - // Copies a span from the given Session ContextStore into the targetContextStore. Used to - // propagate a Span from a Session to transient Session objects such as Transaction and Query. - public static void attachSpanFromStore( - ContextStore sourceContextStore, - S source, - ContextStore targetContextStore, - T target) { - - Context sessionContext = sourceContextStore.get(source); - if (sessionContext == null) { - return; - } - - targetContextStore.putIfAbsent(target, sessionContext); - } -} diff --git a/instrumentation/http-url-connection/http-url-connection.gradle b/instrumentation/http-url-connection/http-url-connection.gradle deleted file mode 100644 index 0b7256c0a4..0000000000 --- a/instrumentation/http-url-connection/http-url-connection.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk() - } -} - -dependencies { - testImplementation group: 'org.springframework', name: 'spring-web', version: '4.3.7.RELEASE' -} diff --git a/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionTest.groovy b/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionTest.groovy index 5ed019ecb8..ca7a2d687e 100644 --- a/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionTest.groovy +++ b/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionTest.groovy @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import io.opentelemetry.instrumentation.test.base.HttpClientTest import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.base.HttpClientTest import spock.lang.Ignore import spock.lang.Requires import spock.lang.Timeout diff --git a/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy b/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy index 85eff54420..822c0ea508 100644 --- a/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy +++ b/instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import io.opentelemetry.instrumentation.test.base.HttpClientTest import io.opentelemetry.api.trace.Span +import io.opentelemetry.instrumentation.test.base.HttpClientTest import spock.lang.Timeout @Timeout(5) diff --git a/instrumentation/http-url-connection/javaagent/src/test/groovy/UrlConnectionTest.groovy b/instrumentation/http-url-connection/javaagent/src/test/groovy/UrlConnectionTest.groovy index c9c5dc5100..b758e49df0 100644 --- a/instrumentation/http-url-connection/javaagent/src/test/groovy/UrlConnectionTest.groovy +++ b/instrumentation/http-url-connection/javaagent/src/test/groovy/UrlConnectionTest.groovy @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +import static io.opentelemetry.api.trace.Span.Kind.CLIENT import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer +import io.opentelemetry.instrumentation.test.AgentTestRunner class UrlConnectionTest extends AgentTestRunner { diff --git a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HeadersInjectAdapter.java b/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HeadersInjectAdapter.java deleted file mode 100644 index 4a7105970e..0000000000 --- a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HeadersInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpurlconnection; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.net.HttpURLConnection; - -public class HeadersInjectAdapter implements TextMapPropagator.Setter { - - public static final HeadersInjectAdapter SETTER = new HeadersInjectAdapter(); - - @Override - public void set(HttpURLConnection carrier, String key, String value) { - carrier.setRequestProperty(key, value); - } -} diff --git a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java b/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java deleted file mode 100644 index 70fe54ac67..0000000000 --- a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpurlconnection; - -import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.HttpUrlConnectionTracer.tracer; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.net.HttpURLConnection; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; - -@AutoService(InstrumentationModule.class) -public class HttpUrlConnectionInstrumentationModule extends InstrumentationModule { - - public HttpUrlConnectionInstrumentationModule() { - super("httpurlconnection"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HttpUrlConnectionInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap("java.net.HttpURLConnection", getClass().getName() + "$HttpUrlState"); - } - - public static class HttpUrlConnectionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("java.net.") - .or(ElementMatchers.nameStartsWith("sun.net")) - // In WebLogic, URL.openConnection() returns its own internal implementation of - // HttpURLConnection, which does not delegate the methods that have to be instrumented to - // the JDK superclass. Therefore it needs to be instrumented directly. - .or(named("weblogic.net.http.HttpURLConnection")) - // This class is a simple delegator. Skip because it does not update its `connected` - // field. - .and(not(named("sun.net.www.protocol.https.HttpsURLConnectionImpl"))) - .and(extendsClass(named("java.net.HttpURLConnection"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(namedOneOf("connect", "getOutputStream", "getInputStream")), - HttpUrlConnectionInstrumentationModule.class.getName() + "$HttpUrlConnectionAdvice"); - } - } - - public static class HttpUrlConnectionAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static HttpUrlState methodEnter( - @Advice.This HttpURLConnection thiz, - @Advice.FieldValue("connected") boolean connected, - @Advice.Local("otelScope") Scope scope) { - - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(HttpURLConnection.class); - if (callDepth > 0) { - return null; - } - - ContextStore contextStore = - InstrumentationContext.get(HttpURLConnection.class, HttpUrlState.class); - HttpUrlState state = contextStore.putIfAbsent(thiz, HttpUrlState.FACTORY); - - synchronized (state) { - if (!state.hasSpan() && !state.isFinished()) { - Span span = state.start(thiz); - if (!connected) { - scope = tracer().startScope(span, thiz); - } - } - return state; - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Enter HttpUrlState state, - @Advice.FieldValue("responseCode") int responseCode, - @Advice.Thrown Throwable throwable, - @Advice.Origin("#m") String methodName, - @Advice.Local("otelScope") Scope scope) { - - if (scope != null) { - scope.close(); - } - if (state == null) { - return; - } - CallDepthThreadLocalMap.reset(HttpURLConnection.class); - - synchronized (state) { - if (state.hasSpan() && !state.isFinished()) { - if (throwable != null) { - state.finishSpan(throwable); - } else if ("getInputStream".equals(methodName)) { - state.finishSpan(responseCode); - } - } - } - } - } - - public static class HttpUrlState { - - public static final ContextStore.Factory FACTORY = - new ContextStore.Factory() { - @Override - public HttpUrlState create() { - return new HttpUrlState(); - } - }; - - private volatile Span span = null; - private volatile boolean finished = false; - - public Span start(HttpURLConnection connection) { - span = tracer().startSpan(connection); - return span; - } - - public boolean hasSpan() { - return span != null; - } - - public boolean isFinished() { - return finished; - } - - public void finishSpan(Throwable throwable) { - tracer().endExceptionally(span, throwable); - span = null; - finished = true; - } - - public void finishSpan(int responseCode) { - /* - * responseCode field is sometimes not populated. - * We can't call getResponseCode() due to some unwanted side-effects - * (e.g. breaks getOutputStream). - */ - if (responseCode > 0) { - // Need to explicitly cast to boxed type to make sure correct method is called. - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/946 - tracer().end(span, (Integer) responseCode); - span = null; - finished = true; - } - } - } -} diff --git a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionTracer.java b/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionTracer.java deleted file mode 100644 index aac7d9a572..0000000000 --- a/instrumentation/http-url-connection/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionTracer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpurlconnection; - -import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.HeadersInjectAdapter.SETTER; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; - -public class HttpUrlConnectionTracer - extends HttpClientTracer { - - private static final HttpUrlConnectionTracer TRACER = new HttpUrlConnectionTracer(); - - public static HttpUrlConnectionTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpURLConnection connection) { - return connection.getRequestMethod(); - } - - @Override - protected URI url(HttpURLConnection connection) throws URISyntaxException { - return connection.getURL().toURI(); - } - - @Override - protected Integer status(Integer status) { - return status; - } - - @Override - protected String requestHeader(HttpURLConnection httpUrlConnection, String name) { - return httpUrlConnection.getRequestProperty(name); - } - - @Override - protected String responseHeader(Integer integer, String name) { - return null; - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.http-url-connection"; - } -} diff --git a/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionResponseCodeOnlyTest.groovy b/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionResponseCodeOnlyTest.groovy deleted file mode 100644 index 8c7f2c72e9..0000000000 --- a/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionResponseCodeOnlyTest.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.Timeout - -@Timeout(5) -class HttpUrlConnectionResponseCodeOnlyTest extends HttpClientTest { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - HttpURLConnection connection = uri.toURL().openConnection() - try { - connection.setRequestMethod(method) - connection.connectTimeout = CONNECT_TIMEOUT_MS - headers.each { connection.setRequestProperty(it.key, it.value) } - connection.setRequestProperty("Connection", "close") - return connection.getResponseCode() - } finally { - callback?.call() - connection.disconnect() - } - } - - @Override - boolean testCircularRedirects() { - false - } -} diff --git a/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionTest.groovy b/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionTest.groovy deleted file mode 100644 index ca7a2d687e..0000000000 --- a/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionTest.groovy +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.Ignore -import spock.lang.Requires -import spock.lang.Timeout -import sun.net.www.protocol.https.HttpsURLConnectionImpl - -@Timeout(5) -class HttpUrlConnectionTest extends HttpClientTest { - - static final RESPONSE = "Hello." - static final STATUS = 200 - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - HttpURLConnection connection = uri.toURL().openConnection() - try { - connection.setRequestMethod(method) - headers.each { connection.setRequestProperty(it.key, it.value) } - connection.setRequestProperty("Connection", "close") - connection.useCaches = true - connection.connectTimeout = CONNECT_TIMEOUT_MS - def parentSpan = Span.current() - def stream = connection.inputStream - assert Span.current() == parentSpan - stream.readLines() - stream.close() - callback?.call() - return connection.getResponseCode() - } finally { - connection.disconnect() - } - } - - @Override - boolean testCircularRedirects() { - false - } - - @Ignore - def "trace request with propagation (useCaches: #useCaches)"() { - setup: - def url = server.address.resolve("/success").toURL() - runUnderTrace("someTrace") { - HttpURLConnection connection = url.openConnection() - connection.useCaches = useCaches - assert activeSpan() != null - def stream = connection.inputStream - def lines = stream.readLines() - stream.close() - assert connection.getResponseCode() == STATUS - assert lines == [RESPONSE] - - // call again to ensure the cycling is ok - connection = url.openConnection() - connection.useCaches = useCaches - assert activeSpan() != null - // call before input stream to test alternate behavior - assert connection.getResponseCode() == STATUS - connection.inputStream - stream = connection.inputStream // one more to ensure state is working - lines = stream.readLines() - stream.close() - assert lines == [RESPONSE] - } - - expect: - assertTraces(3) { - server.distributedRequestTrace(it, 0, traces[2][2]) - server.distributedRequestTrace(it, 1, traces[2][1]) - trace(2, 3) { - span(0) { - name "someTrace" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" STATUS - } - } - span(2) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" STATUS - } - } - } - } - - where: - useCaches << [false, true] - } - - @Ignore - def "trace request without propagation (useCaches: #useCaches)"() { - setup: - def url = server.address.resolve("/success").toURL() - runUnderTrace("someTrace") { - HttpURLConnection connection = url.openConnection() - connection.useCaches = useCaches - connection.addRequestProperty("is-test-server", "false") - assert activeSpan() != null - def stream = connection.inputStream - connection.inputStream // one more to ensure state is working - def lines = stream.readLines() - stream.close() - assert connection.getResponseCode() == STATUS - assert lines == [RESPONSE] - - // call again to ensure the cycling is ok - connection = url.openConnection() - connection.useCaches = useCaches - connection.addRequestProperty("is-test-server", "false") - assert activeSpan() != null - // call before input stream to test alternate behavior - assert connection.getResponseCode() == STATUS - stream = connection.inputStream - lines = stream.readLines() - stream.close() - assert lines == [RESPONSE] - } - - expect: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "someTrace" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" STATUS - } - } - span(2) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" STATUS - } - } - } - } - - where: - useCaches << [false, true] - } - - @Ignore - def "test broken API usage"() { - setup: - def url = server.address.resolve("/success").toURL() - runUnderTrace("someTrace") { - HttpURLConnection connection = url.openConnection() - connection.setRequestProperty("Connection", "close") - connection.addRequestProperty("is-test-server", "false") - assert activeSpan() != null - assert connection.getResponseCode() == STATUS - return connection - } - - expect: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "someTrace" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - errored false - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" STATUS - } - } - } - } - - cleanup: - conn.disconnect() - - where: - iteration << (1..10) - } - - @Ignore - def "test post request"() { - setup: - def url = server.address.resolve("/success").toURL() - runUnderTrace("someTrace") { - HttpURLConnection connection = url.openConnection() - connection.setRequestMethod("POST") - - String urlParameters = "q=ASDF&w=&e=&r=12345&t=" - - // Send post request - connection.setDoOutput(true) - DataOutputStream wr = new DataOutputStream(connection.getOutputStream()) - wr.writeBytes(urlParameters) - wr.flush() - wr.close() - - assert connection.getResponseCode() == STATUS - - def stream = connection.inputStream - def lines = stream.readLines() - stream.close() - assert lines == [RESPONSE] - } - - expect: - assertTraces(2) { - server.distributedRequestTrace(it, 0, traces[1][1]) - trace(1, 2) { - span(0) { - name "someTrace" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name expectedOperationName("POST") - kind CLIENT - childOf span(0) - errored false - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" server.address.port - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "POST" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" STATUS - } - } - } - } - } - - // This test makes no sense on IBM JVM because there is no HttpsURLConnectionImpl class there - @Requires({ !System.getProperty("java.vm.name").contains("IBM J9 VM") }) - def "Make sure we can load HttpsURLConnectionImpl"() { - when: - def instance = new HttpsURLConnectionImpl(null, null, null) - - then: - instance != null - } -} diff --git a/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy b/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy deleted file mode 100644 index 822c0ea508..0000000000 --- a/instrumentation/http-url-connection/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.Timeout - -@Timeout(5) -class HttpUrlConnectionUseCachesFalseTest extends HttpClientTest { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - HttpURLConnection connection = uri.toURL().openConnection() - try { - connection.setRequestMethod(method) - headers.each { connection.setRequestProperty(it.key, it.value) } - connection.setRequestProperty("Connection", "close") - connection.useCaches = false - connection.connectTimeout = CONNECT_TIMEOUT_MS - def parentSpan = Span.current() - def stream = connection.inputStream - assert Span.current() == parentSpan - stream.readLines() - stream.close() - callback?.call() - return connection.getResponseCode() - } finally { - connection.disconnect() - } - } - - @Override - boolean testCircularRedirects() { - false - } -} diff --git a/instrumentation/http-url-connection/src/test/groovy/SpringRestTemplateTest.groovy b/instrumentation/http-url-connection/src/test/groovy/SpringRestTemplateTest.groovy deleted file mode 100644 index b33910846c..0000000000 --- a/instrumentation/http-url-connection/src/test/groovy/SpringRestTemplateTest.groovy +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpMethod -import org.springframework.http.ResponseEntity -import org.springframework.http.client.ClientHttpRequestFactory -import org.springframework.http.client.SimpleClientHttpRequestFactory -import org.springframework.web.client.RestTemplate -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class SpringRestTemplateTest extends HttpClientTest { - - @Shared - ClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory() - @Shared - RestTemplate restTemplate = new RestTemplate(factory) - - def setupSpec() { - factory.connectTimeout = CONNECT_TIMEOUT_MS - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def httpHeaders = new HttpHeaders() - headers.each { httpHeaders.put(it.key, [it.value]) } - def request = new HttpEntity(httpHeaders) - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.resolve(method), request, String) - callback?.call() - return response.statusCode.value() - } - - @Override - boolean testCircularRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - // FIXME: exception wrapped in ResourceAccessException - return false - } -} diff --git a/instrumentation/http-url-connection/src/test/groovy/UrlConnectionTest.groovy b/instrumentation/http-url-connection/src/test/groovy/UrlConnectionTest.groovy deleted file mode 100644 index b758e49df0..0000000000 --- a/instrumentation/http-url-connection/src/test/groovy/UrlConnectionTest.groovy +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer -import io.opentelemetry.instrumentation.test.AgentTestRunner - -class UrlConnectionTest extends AgentTestRunner { - - def "trace request with connection failure #scheme"() { - when: - runUnderTrace("someTrace") { - URLConnection connection = url.openConnection() - connection.setConnectTimeout(10000) - connection.setReadTimeout(10000) - assert Span.current() != null - connection.inputStream - } - - then: - thrown ConnectException - - expect: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "someTrace" - hasNoParent() - errored true - errorEvent ConnectException, String - } - span(1) { - name expectedOperationName("GET") - kind CLIENT - childOf span(0) - errored true - errorEvent ConnectException, String - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key()}" UNUSABLE_PORT - "${SemanticAttributes.HTTP_URL.key()}" "$url" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - } - } - } - } - - where: - scheme << ["http", "https"] - - url = new URI("$scheme://localhost:$UNUSABLE_PORT").toURL() - } - - String expectedOperationName(String method) { - return method != null ? "HTTP $method" : HttpClientTracer.DEFAULT_SPAN_NAME - } -} diff --git a/instrumentation/hystrix-1.4/hystrix-1.4.gradle b/instrumentation/hystrix-1.4/hystrix-1.4.gradle deleted file mode 100644 index d8256fc1c2..0000000000 --- a/instrumentation/hystrix-1.4/hystrix-1.4.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.netflix.hystrix" - module = 'hystrix-core' - versions = "[1.4.0,)" - } -} - -dependencies { - implementation project(':instrumentation:rxjava-1.0:library') - - library group: 'com.netflix.hystrix', name: 'hystrix-core', version: '1.4.0' - library group: 'io.reactivex', name: 'rxjava', version: '1.0.7' -} diff --git a/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentationModule.java b/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentationModule.java deleted file mode 100644 index afc59d0bc6..0000000000 --- a/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixInstrumentationModule.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hystrix; - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL; -import static io.opentelemetry.javaagent.instrumentation.hystrix.HystrixTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import com.google.auto.service.AutoService; -import com.netflix.hystrix.HystrixInvokableInfo; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.rxjava.TracedOnSubscribe; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import rx.Observable; - -@AutoService(InstrumentationModule.class) -public class HystrixInstrumentationModule extends InstrumentationModule { - - private static final String OPERATION_NAME = "hystrix.cmd"; - - public HystrixInstrumentationModule() { - super("hystrix", "hystrix-1.4"); - } - - @Override - protected String[] additionalHelperClassNames() { - return new String[] { - "rx.__OpenTelemetryTracingUtil", - }; - } - - @Override - public List typeInstrumentations() { - return singletonList(new HystrixCommandInstrumentation()); - } - - public static class HystrixCommandInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed( - "com.netflix.hystrix.HystrixCommand", "com.netflix.hystrix.HystrixObservableCommand"); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass( - namedOneOf( - "com.netflix.hystrix.HystrixCommand", - "com.netflix.hystrix.HystrixObservableCommand")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("getExecutionObservable").and(returns(named("rx.Observable"))), - HystrixInstrumentationModule.class.getName() + "$ExecuteAdvice"); - transformers.put( - named("getFallbackObservable").and(returns(named("rx.Observable"))), - HystrixInstrumentationModule.class.getName() + "$FallbackAdvice"); - return transformers; - } - } - - public static class ExecuteAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.This HystrixInvokableInfo command, - @Advice.Return(readOnly = false) Observable result, - @Advice.Thrown Throwable throwable) { - - result = Observable.create(new HystrixOnSubscribe<>(result, command, "execute")); - } - } - - public static class FallbackAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.This HystrixInvokableInfo command, - @Advice.Return(readOnly = false) Observable result, - @Advice.Thrown Throwable throwable) { - - result = Observable.create(new HystrixOnSubscribe<>(result, command, "fallback")); - } - } - - public static class HystrixOnSubscribe extends TracedOnSubscribe { - private final HystrixInvokableInfo command; - private final String methodName; - - public HystrixOnSubscribe( - Observable originalObservable, HystrixInvokableInfo command, String methodName) { - super(originalObservable, OPERATION_NAME, tracer(), INTERNAL); - - this.command = command; - this.methodName = methodName; - } - - @Override - protected void decorateSpan(Span span) { - tracer().onCommand(span, command, methodName); - } - } -} diff --git a/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTracer.java b/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTracer.java deleted file mode 100644 index 2fee162dcc..0000000000 --- a/instrumentation/hystrix-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixTracer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.hystrix; - -import com.netflix.hystrix.HystrixInvokableInfo; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; - -public class HystrixTracer extends BaseTracer { - private static final HystrixTracer TRACER = new HystrixTracer(); - - public static HystrixTracer tracer() { - return TRACER; - } - - private final boolean extraTags; - - private HystrixTracer() { - extraTags = Config.get().getBooleanProperty("otel.instrumentation.hystrix.tags", false); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.hystrix"; - } - - public void onCommand(Span span, HystrixInvokableInfo command, String methodName) { - if (command != null) { - String commandName = command.getCommandKey().name(); - String groupName = command.getCommandGroup().name(); - boolean circuitOpen = command.isCircuitBreakerOpen(); - - String spanName = groupName + "." + commandName + "." + methodName; - - span.updateName(spanName); - if (extraTags) { - span.setAttribute("hystrix.command", commandName); - span.setAttribute("hystrix.group", groupName); - span.setAttribute("hystrix.circuit-open", circuitOpen); - } - } - } -} diff --git a/instrumentation/hystrix-1.4/src/test/groovy/HystrixObservableChainTest.groovy b/instrumentation/hystrix-1.4/src/test/groovy/HystrixObservableChainTest.groovy deleted file mode 100644 index 18e38d44bf..0000000000 --- a/instrumentation/hystrix-1.4/src/test/groovy/HystrixObservableChainTest.groovy +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.netflix.hystrix.HystrixObservableCommand -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import rx.Observable -import rx.schedulers.Schedulers - -class HystrixObservableChainTest extends AgentTestRunner { - static { - // Disable so failure testing below doesn't inadvertently change the behavior. - System.setProperty("hystrix.command.default.circuitBreaker.enabled", "false") - - // Uncomment for debugging: - // System.setProperty("hystrix.command.default.execution.timeout.enabled", "false") - } - - static final PREVIOUS_CONFIG = ConfigUtils.updateConfig { - it.setProperty("otel.instrumentation.hystrix.tags", "true") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - def "test command #action"() { - setup: - - def result = runUnderTrace("parent") { - def val = new HystrixObservableCommand(asKey("ExampleGroup")) { - private String tracedMethod() { - getTestTracer().spanBuilder("tracedMethod").startSpan().end() - return "Hello" - } - - @Override - protected Observable construct() { - Observable.defer { - Observable.just(tracedMethod()) - } - .subscribeOn(Schedulers.immediate()) - } - }.toObservable() - .subscribeOn(Schedulers.io()) - .map { - it.toUpperCase() - }.flatMap { str -> - new HystrixObservableCommand(asKey("OtherGroup")) { - private String anotherTracedMethod() { - getTestTracer().spanBuilder("anotherTracedMethod").startSpan().end() - return "$str!" - } - - @Override - protected Observable construct() { - Observable.defer { - Observable.just(anotherTracedMethod()) - } - .subscribeOn(Schedulers.computation()) - } - }.toObservable() - .subscribeOn(Schedulers.trampoline()) - }.toBlocking().first() - return val - } - - expect: - result == "HELLO!" - - assertTraces(1) { - trace(0, 5) { - span(0) { - name "parent" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name "ExampleGroup.HystrixObservableChainTest\$1.execute" - childOf span(0) - errored false - attributes { - "hystrix.command" "HystrixObservableChainTest\$1" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - span(2) { - name "tracedMethod" - childOf span(1) - errored false - attributes { - } - } - span(3) { - name "OtherGroup.HystrixObservableChainTest\$2.execute" - childOf span(1) - errored false - attributes { - "hystrix.command" "HystrixObservableChainTest\$2" - "hystrix.group" "OtherGroup" - "hystrix.circuit-open" false - } - } - span(4) { - name "anotherTracedMethod" - childOf span(3) - errored false - attributes { - } - } - } - } - } -} diff --git a/instrumentation/hystrix-1.4/src/test/groovy/HystrixObservableTest.groovy b/instrumentation/hystrix-1.4/src/test/groovy/HystrixObservableTest.groovy deleted file mode 100644 index 2c784ccb88..0000000000 --- a/instrumentation/hystrix-1.4/src/test/groovy/HystrixObservableTest.groovy +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.netflix.hystrix.HystrixObservable -import com.netflix.hystrix.HystrixObservableCommand -import com.netflix.hystrix.exception.HystrixRuntimeException -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import java.util.concurrent.BlockingQueue -import java.util.concurrent.LinkedBlockingQueue -import rx.Observable -import rx.schedulers.Schedulers - -class HystrixObservableTest extends AgentTestRunner { - static { - // Disable so failure testing below doesn't inadvertently change the behavior. - System.setProperty("hystrix.command.default.circuitBreaker.enabled", "false") - - // Uncomment for debugging: - // System.setProperty("hystrix.command.default.execution.timeout.enabled", "false") - } - - static final PREVIOUS_CONFIG = ConfigUtils.updateConfig { - it.setProperty("otel.instrumentation.hystrix.tags", "true") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - def "test command #action"() { - setup: - def observeOnFn = observeOn - def subscribeOnFn = subscribeOn - def result = runUnderTrace("parent") { - def val = operation new HystrixObservableCommand(asKey("ExampleGroup")) { - private String tracedMethod() { - getTestTracer().spanBuilder("tracedMethod").startSpan().end() - return "Hello!" - } - - @Override - protected Observable construct() { - def obs = Observable.defer { - Observable.just(tracedMethod()).repeat(1) - } - if (observeOnFn) { - obs = obs.observeOn(observeOnFn) - } - if (subscribeOnFn) { - obs = obs.subscribeOn(subscribeOnFn) - } - return obs - } - } - return val - } - - expect: - TRANSFORMED_CLASSES_NAMES.contains("HystrixObservableTest\$1") - result == "Hello!" - - assertTraces(1) { - trace(0, 3) { - span(0) { - name "parent" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name "ExampleGroup.HystrixObservableTest\$1.execute" - childOf span(0) - errored false - attributes { - "hystrix.command" "HystrixObservableTest\$1" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - span(2) { - name "tracedMethod" - childOf span(1) - errored false - attributes { - } - } - } - } - - where: - action | observeOn | subscribeOn | operation - "toObservable" | null | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-I" | Schedulers.immediate() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-T" | Schedulers.trampoline() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-C" | Schedulers.computation() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-IO" | Schedulers.io() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-NT" | Schedulers.newThread() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+I" | null | Schedulers.immediate() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+T" | null | Schedulers.trampoline() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+C" | null | Schedulers.computation() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+IO" | null | Schedulers.io() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+NT" | null | Schedulers.newThread() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "observe" | null | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-I" | Schedulers.immediate() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-T" | Schedulers.trampoline() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-C" | Schedulers.computation() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-IO" | Schedulers.io() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-NT" | Schedulers.newThread() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+I" | null | Schedulers.immediate() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+T" | null | Schedulers.trampoline() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+C" | null | Schedulers.computation() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+IO" | null | Schedulers.io() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+NT" | null | Schedulers.newThread() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "toObservable block" | Schedulers.computation() | Schedulers.newThread() | { HystrixObservable cmd -> - BlockingQueue queue = new LinkedBlockingQueue() - def subscription = cmd.toObservable().subscribe { next -> - queue.put(next) - } - def val = queue.take() - subscription.unsubscribe() - return val - } - } - - def "test command #action fallback"() { - setup: - def observeOnFn = observeOn - def subscribeOnFn = subscribeOn - def result = runUnderTrace("parent") { - def val = operation new HystrixObservableCommand(asKey("ExampleGroup")) { - @Override - protected Observable construct() { - def err = Observable.defer { - Observable.error(new IllegalArgumentException()).repeat(1) - } - if (observeOnFn) { - err = err.observeOn(observeOnFn) - } - if (subscribeOnFn) { - err = err.subscribeOn(subscribeOnFn) - } - return err - } - - protected Observable resumeWithFallback() { - return Observable.just("Fallback!").repeat(1) - } - } - return val - } - - expect: - TRANSFORMED_CLASSES_NAMES.contains("HystrixObservableTest\$2") - result == "Fallback!" - - assertTraces(1) { - trace(0, 3) { - span(0) { - name "parent" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name "ExampleGroup.HystrixObservableTest\$2.execute" - childOf span(0) - errored true - errorEvent(IllegalArgumentException) - attributes { - "hystrix.command" "HystrixObservableTest\$2" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - span(2) { - name "ExampleGroup.HystrixObservableTest\$2.fallback" - childOf span(1) - errored false - attributes { - "hystrix.command" "HystrixObservableTest\$2" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - } - } - - where: - action | observeOn | subscribeOn | operation - "toObservable" | null | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-I" | Schedulers.immediate() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-T" | Schedulers.trampoline() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-C" | Schedulers.computation() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-IO" | Schedulers.io() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-NT" | Schedulers.newThread() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+I" | null | Schedulers.immediate() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+T" | null | Schedulers.trampoline() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+C" | null | Schedulers.computation() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+IO" | null | Schedulers.io() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+NT" | null | Schedulers.newThread() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "observe" | null | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-I" | Schedulers.immediate() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-T" | Schedulers.trampoline() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-C" | Schedulers.computation() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-IO" | Schedulers.io() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-NT" | Schedulers.newThread() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+I" | null | Schedulers.immediate() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+T" | null | Schedulers.trampoline() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+C" | null | Schedulers.computation() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+IO" | null | Schedulers.io() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+NT" | null | Schedulers.newThread() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "toObservable block" | null | null | { HystrixObservable cmd -> - BlockingQueue queue = new LinkedBlockingQueue() - def subscription = cmd.toObservable().subscribe { next -> - queue.put(next) - } - def val = queue.take() - subscription.unsubscribe() - return val - } - } - - def "test no fallback results in error for #action"() { - setup: - def observeOnFn = observeOn - def subscribeOnFn = subscribeOn - - when: - runUnderTrace("parent") { - operation new HystrixObservableCommand(asKey("FailingGroup")) { - - @Override - protected Observable construct() { - def err = Observable.defer { - Observable.error(new IllegalArgumentException()) - } - if (observeOnFn) { - err = err.observeOn(observeOnFn) - } - if (subscribeOnFn) { - err = err.subscribeOn(subscribeOnFn) - } - return err - } - } - } - - then: - TRANSFORMED_CLASSES_NAMES.contains("HystrixObservableTest\$3") - def err = thrown HystrixRuntimeException - err.cause instanceof IllegalArgumentException - - assertTraces(1) { - trace(0, 3) { - span(0) { - name "parent" - hasNoParent() - errored true - errorEvent(HystrixRuntimeException, "HystrixObservableTest\$3 failed and no fallback available.") - } - span(1) { - name "FailingGroup.HystrixObservableTest\$3.execute" - childOf span(0) - errored true - errorEvent(IllegalArgumentException) - attributes { - "hystrix.command" "HystrixObservableTest\$3" - "hystrix.group" "FailingGroup" - "hystrix.circuit-open" false - } - } - span(2) { - name "FailingGroup.HystrixObservableTest\$3.fallback" - childOf span(1) - errored true - errorEvent(UnsupportedOperationException, "No fallback available.") - attributes { - "hystrix.command" "HystrixObservableTest\$3" - "hystrix.group" "FailingGroup" - "hystrix.circuit-open" false - } - } - } - } - - where: - action | observeOn | subscribeOn | operation - "toObservable" | null | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-I" | Schedulers.immediate() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-T" | Schedulers.trampoline() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-C" | Schedulers.computation() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-IO" | Schedulers.io() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable-NT" | Schedulers.newThread() | null | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+I" | null | Schedulers.immediate() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+T" | null | Schedulers.trampoline() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+C" | null | Schedulers.computation() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+IO" | null | Schedulers.io() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "toObservable+NT" | null | Schedulers.newThread() | { HystrixObservable cmd -> cmd.toObservable().toBlocking().first() } - "observe" | null | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-I" | Schedulers.immediate() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-T" | Schedulers.trampoline() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-C" | Schedulers.computation() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-IO" | Schedulers.io() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe-NT" | Schedulers.newThread() | null | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+I" | null | Schedulers.immediate() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+T" | null | Schedulers.trampoline() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+C" | null | Schedulers.computation() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+IO" | null | Schedulers.io() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "observe+NT" | null | Schedulers.newThread() | { HystrixObservable cmd -> cmd.observe().toBlocking().first() } - "toObservable block" | Schedulers.computation() | Schedulers.newThread() | { HystrixObservable cmd -> - def queue = new LinkedBlockingQueue() - def subscription = cmd.toObservable().subscribe({ next -> - queue.put(new Exception("Unexpectedly got a next")) - }, { next -> - queue.put(next) - }) - Throwable ex = queue.take() - subscription.unsubscribe() - throw ex - } - } -} diff --git a/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy b/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy deleted file mode 100644 index 3e050937a6..0000000000 --- a/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.netflix.hystrix.HystrixCommand -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import java.util.concurrent.BlockingQueue -import java.util.concurrent.LinkedBlockingQueue -import spock.lang.Timeout - -@Timeout(10) -class HystrixTest extends AgentTestRunner { - static { - // Disable so failure testing below doesn't inadvertently change the behavior. - System.setProperty("hystrix.command.default.circuitBreaker.enabled", "false") - - // Uncomment for debugging: - // System.setProperty("hystrix.command.default.execution.timeout.enabled", "false") - } - - static final PREVIOUS_CONFIG = ConfigUtils.updateConfig { - it.setProperty("otel.instrumentation.hystrix.tags", "true") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - def "test command #action"() { - setup: - def command = new HystrixCommand(asKey("ExampleGroup")) { - @Override - protected String run() throws Exception { - return tracedMethod() - } - - private String tracedMethod() { - getTestTracer().spanBuilder("tracedMethod").startSpan().end() - return "Hello!" - } - } - def result = runUnderTrace("parent") { - operation(command) - } - expect: - TRANSFORMED_CLASSES_NAMES.contains("HystrixTest\$1") - result == "Hello!" - - assertTraces(1) { - trace(0, 3) { - span(0) { - name "parent" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name "ExampleGroup.HystrixTest\$1.execute" - childOf span(0) - errored false - attributes { - "hystrix.command" "HystrixTest\$1" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - span(2) { - name "tracedMethod" - childOf span(1) - errored false - attributes { - } - } - } - } - - where: - action | operation - "execute" | { HystrixCommand cmd -> cmd.execute() } - "queue" | { HystrixCommand cmd -> cmd.queue().get() } - "toObservable" | { HystrixCommand cmd -> cmd.toObservable().toBlocking().first() } - "observe" | { HystrixCommand cmd -> cmd.observe().toBlocking().first() } - "observe block" | { HystrixCommand cmd -> - BlockingQueue queue = new LinkedBlockingQueue() - cmd.observe().subscribe { next -> - queue.put(next) - } - queue.take() - } - } - - def "test command #action fallback"() { - setup: - def command = new HystrixCommand(asKey("ExampleGroup")) { - @Override - protected String run() throws Exception { - throw new IllegalArgumentException() - } - - protected String getFallback() { - return "Fallback!" - } - } - def result = runUnderTrace("parent") { - operation(command) - } - expect: - TRANSFORMED_CLASSES_NAMES.contains("HystrixTest\$2") - result == "Fallback!" - - assertTraces(1) { - trace(0, 3) { - span(0) { - name "parent" - hasNoParent() - errored false - attributes { - } - } - span(1) { - name "ExampleGroup.HystrixTest\$2.execute" - childOf span(0) - errored true - errorEvent(IllegalArgumentException) - attributes { - "hystrix.command" "HystrixTest\$2" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - span(2) { - name "ExampleGroup.HystrixTest\$2.fallback" - childOf span(1) - errored false - attributes { - "hystrix.command" "HystrixTest\$2" - "hystrix.group" "ExampleGroup" - "hystrix.circuit-open" false - } - } - } - } - - where: - action | operation - "execute" | { HystrixCommand cmd -> cmd.execute() } - "queue" | { HystrixCommand cmd -> cmd.queue().get() } - "toObservable" | { HystrixCommand cmd -> cmd.toObservable().toBlocking().first() } - "observe" | { HystrixCommand cmd -> cmd.observe().toBlocking().first() } - "observe block" | { HystrixCommand cmd -> - BlockingQueue queue = new LinkedBlockingQueue() - cmd.observe().subscribe { next -> - queue.put(next) - } - queue.take() - } - } -} diff --git a/instrumentation/java-httpclient/java-httpclient.gradle b/instrumentation/java-httpclient/java-httpclient.gradle deleted file mode 100644 index 0465275b3e..0000000000 --- a/instrumentation/java-httpclient/java-httpclient.gradle +++ /dev/null @@ -1,11 +0,0 @@ -ext { - minJavaVersionForTests = JavaVersion.VERSION_11 -} - -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk() - } -} diff --git a/instrumentation/java-httpclient/javaagent/src/test/groovy/JdkHttpClientTest.groovy b/instrumentation/java-httpclient/javaagent/src/test/groovy/JdkHttpClientTest.groovy index 098ff229e0..03c061437e 100644 --- a/instrumentation/java-httpclient/javaagent/src/test/groovy/JdkHttpClientTest.groovy +++ b/instrumentation/java-httpclient/javaagent/src/test/groovy/JdkHttpClientTest.groovy @@ -5,8 +5,8 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import io.opentelemetry.instrumentation.test.base.HttpClientTest import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.base.HttpClientTest import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse diff --git a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpClientInstrumentation.java b/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpClientInstrumentation.java deleted file mode 100644 index 988ffbe43e..0000000000 --- a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpClientInstrumentation.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpclient; - -import static io.opentelemetry.javaagent.instrumentation.httpclient.JdkHttpClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class HttpClientInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("java.net.http.HttpClient"); - } - - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("java.net.") - .or(nameStartsWith("jdk.internal.")) - .and(not(named("jdk.internal.net.http.HttpClientFacade"))) - .and(extendsClass(named("java.net.http.HttpClient"))); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - - transformers.put( - isMethod() - .and(named("send")) - .and(isPublic()) - .and(takesArguments(2)) - .and(takesArgument(0, named("java.net.http.HttpRequest"))), - HttpClientInstrumentation.class.getName() + "$SendAdvice"); - - transformers.put( - isMethod() - .and(named("sendAsync")) - .and(isPublic()) - .and(takesArgument(0, named("java.net.http.HttpRequest"))), - HttpClientInstrumentation.class.getName() + "$SendAsyncAdvice"); - - return transformers; - } - - public static class SendAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(value = 0) HttpRequest httpRequest, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(httpRequest); - if (span.getSpanContext().isValid()) { - scope = tracer().startScope(span, httpRequest); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return HttpResponse result, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable == null) { - tracer().end(span, result); - } else { - tracer().endExceptionally(span, result, throwable); - } - } - } - } - - public static class SendAsyncAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(value = 0) HttpRequest httpRequest, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(httpRequest); - if (span.getSpanContext().isValid()) { - scope = tracer().startScope(span, httpRequest); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return(readOnly = false) CompletableFuture> future, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, null, throwable); - } else { - future = future.whenComplete(new ResponseConsumer(span)); - } - } - } - } -} diff --git a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpClientInstrumentationModule.java b/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpClientInstrumentationModule.java deleted file mode 100644 index d7b26fd6ef..0000000000 --- a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpClientInstrumentationModule.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpclient; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class HttpClientInstrumentationModule extends InstrumentationModule { - public HttpClientInstrumentationModule() { - super("httpclient"); - } - - @Override - public List typeInstrumentations() { - return asList(new HttpClientInstrumentation(), new HttpHeadersInstrumentation()); - } -} diff --git a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpHeadersInjectAdapter.java b/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpHeadersInjectAdapter.java deleted file mode 100644 index 8f15d52cbb..0000000000 --- a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpHeadersInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpclient; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.net.http.HttpRequest; - -/** Context propagation is implemented via {@link HttpHeadersInstrumentation}. */ -public class HttpHeadersInjectAdapter implements TextMapPropagator.Setter { - public static final HttpHeadersInjectAdapter SETTER = new HttpHeadersInjectAdapter(); - - @Override - public void set(HttpRequest carrier, String key, String value) { - // Don't do anything because headers are immutable - } -} diff --git a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpHeadersInstrumentation.java b/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpHeadersInstrumentation.java deleted file mode 100644 index 807c51e4a3..0000000000 --- a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/HttpHeadersInstrumentation.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpclient; - -import static io.opentelemetry.javaagent.instrumentation.httpclient.JdkHttpClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.net.http.HttpHeaders; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class HttpHeadersInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("java.net.") - .or(nameStartsWith("jdk.internal.")) - .and(extendsClass(named("java.net.http.HttpRequest"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("headers")), - HttpHeadersInstrumentation.class.getName() + "$HeadersAdvice"); - } - - public static class HeadersAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit(@Advice.Return(readOnly = false) HttpHeaders headers) { - if (Java8BytecodeBridge.currentSpan().isRecording()) { - headers = tracer().inject(headers); - } - } - } -} diff --git a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JdkHttpClientTracer.java b/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JdkHttpClientTracer.java deleted file mode 100644 index bc9eedd7bd..0000000000 --- a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JdkHttpClientTracer.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpclient; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpClient.Version; -import java.net.http.HttpHeaders; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletionException; - -public class JdkHttpClientTracer - extends HttpClientTracer> { - private static final JdkHttpClientTracer TRACER = new JdkHttpClientTracer(); - - public static JdkHttpClientTracer tracer() { - return TRACER; - } - - public Depth getCallDepth() { - return CallDepthThreadLocalMap.getCallDepth(HttpClient.class); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.java-httpclient"; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.method(); - } - - @Override - protected URI url(HttpRequest httpRequest) { - return httpRequest.uri(); - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.statusCode(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().firstValue(name).orElse(null); - } - - @Override - protected String responseHeader(HttpResponse httpResponse, String name) { - return httpResponse.headers().firstValue(name).orElse(null); - } - - @Override - protected Span onResponse(Span span, HttpResponse httpResponse) { - span = super.onResponse(span, httpResponse); - - if (httpResponse != null) { - span.setAttribute( - SemanticAttributes.HTTP_FLAVOR, - httpResponse.version() == Version.HTTP_1_1 ? "1.1" : "2.0"); - } - - return span; - } - - @Override - protected Setter getSetter() { - return HttpHeadersInjectAdapter.SETTER; - } - - @Override - protected Throwable unwrapThrowable(Throwable throwable) { - if (throwable instanceof CompletionException) { - return throwable.getCause(); - } - return super.unwrapThrowable(throwable); - } - - public HttpHeaders inject(HttpHeaders original) { - Map> headerMap = new HashMap<>(); - - OpenTelemetry.getGlobalPropagators() - .getTextMapPropagator() - .inject( - Context.current(), - headerMap, - (carrier, key, value) -> carrier.put(key, Collections.singletonList(value))); - headerMap.putAll(original.map()); - - return HttpHeaders.of(headerMap, (s, s2) -> true); - } -} diff --git a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/ResponseConsumer.java b/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/ResponseConsumer.java deleted file mode 100644 index 21c7efc3e3..0000000000 --- a/instrumentation/java-httpclient/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/ResponseConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.httpclient; - -import static io.opentelemetry.javaagent.instrumentation.httpclient.JdkHttpClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import java.net.http.HttpResponse; -import java.util.function.BiConsumer; - -public class ResponseConsumer implements BiConsumer, Throwable> { - private final Span span; - - public ResponseConsumer(Span span) { - this.span = span; - } - - @Override - public void accept(HttpResponse httpResponse, Throwable throwable) { - if (throwable == null) { - tracer().end(span, httpResponse); - } else { - tracer().endExceptionally(span, httpResponse, throwable); - } - } -} diff --git a/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientAsyncTest.groovy b/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientAsyncTest.groovy deleted file mode 100644 index fd560d2b44..0000000000 --- a/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientAsyncTest.groovy +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.net.http.HttpRequest -import java.net.http.HttpResponse - -class JdkHttpClientAsyncTest extends JdkHttpClientTest { - - @Override - HttpResponse send(HttpRequest request) { - return client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).get() - } -} diff --git a/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientSyncTest.groovy b/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientSyncTest.groovy deleted file mode 100644 index 7ea91a918f..0000000000 --- a/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientSyncTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.net.http.HttpRequest -import java.net.http.HttpResponse - -class JdkHttpClientSyncTest extends JdkHttpClientTest { - - @Override - HttpResponse send(HttpRequest request) { - return client.send(request, HttpResponse.BodyHandlers.ofString()) - } - -} diff --git a/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientTest.groovy b/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientTest.groovy deleted file mode 100644 index 03c061437e..0000000000 --- a/instrumentation/java-httpclient/src/test/groovy/JdkHttpClientTest.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.net.http.HttpClient -import java.net.http.HttpRequest -import java.net.http.HttpResponse -import java.time.Duration -import java.time.temporal.ChronoUnit -import spock.lang.Requires -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -abstract class JdkHttpClientTest extends HttpClientTest { - - @Shared - def client = HttpClient.newBuilder().connectTimeout(Duration.of(CONNECT_TIMEOUT_MS, - ChronoUnit.MILLIS)).followRedirects(HttpClient.Redirect.NORMAL).build() - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - - def builder = HttpRequest.newBuilder().uri(uri).method(method, HttpRequest.BodyPublishers.noBody()) - - headers.entrySet().each { - builder.header(it.key, it.value) - } - def request = builder.build() - - def resp = send(request) - callback?.call() - return resp.statusCode() - } - - abstract HttpResponse send(HttpRequest request) - - @Override - boolean testCircularRedirects() { - return false - } - - //We override this test below because it produces somewhat different attributes - @Override - boolean testRemoteConnection() { - return false - } - - @Requires({ !System.getProperty("java.vm.name").contains("IBM J9 VM") }) - def "test https request"() { - given: - def uri = new URI("https://www.google.com/") - - when: - def status = doRequest(method, uri) - - then: - status == 200 - assertTraces(1) { - trace(0, 1 + extraClientSpans()) { - span(0) { - hasNoParent() - name expectedOperationName(method) - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" uri.host - "${SemanticAttributes.NET_PEER_IP.key()}" { it == null || it == "127.0.0.1" } - // Optional - "${SemanticAttributes.NET_PEER_PORT.key()}" uri.port > 0 ? uri.port : { it == null || it == 443 } - "${SemanticAttributes.HTTP_URL.key()}" { it == "${uri}" || it == "${removeFragment(uri)}" } - "${SemanticAttributes.HTTP_METHOD.key()}" method - "${SemanticAttributes.HTTP_FLAVOR.key()}" "2.0" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" status - } - } - } - } - - where: - method = "HEAD" - } - -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/jaxrs-client-1.1.gradle b/instrumentation/jaxrs-client/jaxrs-client-1.1/jaxrs-client-1.1.gradle deleted file mode 100644 index 58142ff156..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/jaxrs-client-1.1.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.sun.jersey" - module = "jersey-client" - versions = "[1.1,]" - skipVersions += ['1.0.3-atlassian-1-logpatch', '1.8-atlassian-6'] - assertInverse = true - } -} - -dependencies { - library group: 'com.sun.jersey', name: 'jersey-client', version: '1.1.4' -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/InjectAdapter.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/InjectAdapter.java deleted file mode 100644 index 40f3a7108d..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/InjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; - -import com.sun.jersey.api.client.ClientRequest; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public final class InjectAdapter implements TextMapPropagator.Setter { - - public static final InjectAdapter SETTER = new InjectAdapter(); - - @Override - public void set(ClientRequest carrier, String key, String value) { - carrier.getHeaders().putSingle(key, value); - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientInstrumentationModule.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientInstrumentationModule.java deleted file mode 100644 index 66fa3f38f4..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientInstrumentationModule.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; - -import static io.opentelemetry.instrumentation.api.tracer.HttpServerTracer.CONTEXT_ATTRIBUTE; -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1.JaxRsClientV1Tracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import com.sun.jersey.api.client.ClientHandler; -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class JaxRsClientInstrumentationModule extends InstrumentationModule { - - public JaxRsClientInstrumentationModule() { - super("jaxrs-client", "jaxrs-client-1.1"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ClientHandlerInstrumentation()); - } - - public static class ClientHandlerInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.sun.jersey.api.client.ClientHandler"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("com.sun.jersey.api.client.ClientHandler")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("handle") - .and(takesArgument(0, extendsClass(named("com.sun.jersey.api.client.ClientRequest")))) - .and(returns(extendsClass(named("com.sun.jersey.api.client.ClientResponse")))), - JaxRsClientInstrumentationModule.class.getName() + "$HandleAdvice"); - } - } - - public static class HandleAdvice { - - @Advice.OnMethodEnter - public static void onEnter( - @Advice.Argument(0) ClientRequest request, - @Advice.This ClientHandler thisObj, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - // WARNING: this might be a chain...so we only have to trace the first in the chain. - boolean isRootClientHandler = null == request.getProperties().get(CONTEXT_ATTRIBUTE); - if (isRootClientHandler) { - span = tracer().startSpan(request); - scope = tracer().startScope(span, request); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Return ClientResponse response, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope != null) { - scope.close(); - } - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span, response); - } - } - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientV1Tracer.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientV1Tracer.java deleted file mode 100644 index b8ff93b259..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientV1Tracer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1.InjectAdapter.SETTER; - -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; - -public class JaxRsClientV1Tracer - extends HttpClientTracer { - private static final JaxRsClientV1Tracer TRACER = new JaxRsClientV1Tracer(); - - public static JaxRsClientV1Tracer tracer() { - return TRACER; - } - - @Override - protected String method(ClientRequest httpRequest) { - return httpRequest.getMethod(); - } - - @Override - protected URI url(ClientRequest httpRequest) { - return httpRequest.getURI(); - } - - @Override - protected Integer status(ClientResponse clientResponse) { - return clientResponse.getStatus(); - } - - @Override - protected String requestHeader(ClientRequest clientRequest, String name) { - Object header = clientRequest.getHeaders().getFirst(name); - return header != null ? header.toString() : null; - } - - @Override - protected String responseHeader(ClientResponse clientResponse, String name) { - return clientResponse.getHeaders().getFirst(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jaxrs-client"; - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/test/groovy/JaxRsClientV1Test.groovy b/instrumentation/jaxrs-client/jaxrs-client-1.1/src/test/groovy/JaxRsClientV1Test.groovy deleted file mode 100644 index 7411649e61..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/src/test/groovy/JaxRsClientV1Test.groovy +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.sun.jersey.api.client.Client -import com.sun.jersey.api.client.ClientResponse -import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter -import com.sun.jersey.api.client.filter.LoggingFilter -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class JaxRsClientV1Test extends HttpClientTest { - - @Shared - Client client = Client.create() - - def setupSpec() { - client.setConnectTimeout(CONNECT_TIMEOUT_MS) - // Add filters to ensure spans aren't duplicated. - client.addFilter(new LoggingFilter()) - client.addFilter(new GZIPContentEncodingFilter()) - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def resource = client.resource(uri).requestBuilder - headers.each { resource.header(it.key, it.value) } - def body = BODY_METHODS.contains(method) ? "" : null - ClientResponse response = resource.method(method, ClientResponse, body) - callback?.call() - - return response.status - } - - boolean testCircularRedirects() { - false - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/javaagent/src/test/groovy/JaxRsClientTest.groovy b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/javaagent/src/test/groovy/JaxRsClientTest.groovy index efad26dbd7..7c940fc03f 100644 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/javaagent/src/test/groovy/JaxRsClientTest.groovy +++ b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/javaagent/src/test/groovy/JaxRsClientTest.groovy @@ -5,8 +5,8 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import io.opentelemetry.instrumentation.test.base.HttpClientTest import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.base.HttpClientTest import java.util.concurrent.TimeUnit import javax.ws.rs.client.Client import javax.ws.rs.client.ClientBuilder diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/jaxrs-client-2.0-common.gradle b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/jaxrs-client-2.0-common.gradle deleted file mode 100644 index 4cf947965a..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/jaxrs-client-2.0-common.gradle +++ /dev/null @@ -1,42 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "javax.ws.rs" - module = "javax.ws.rs-api" - versions = "[2.0,)" - } - pass { - // We want to support the dropwizard clients too. - group = 'io.dropwizard' - module = 'dropwizard-client' - versions = "[0.8.0,)" - assertInverse = true - } -} - -dependencies { - compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0.1' - compileOnly group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' - - testImplementation project(':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-jersey-2.0') - testImplementation project(':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-resteasy-2.0') - - testImplementation group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0.1' - - testLibrary group: 'org.glassfish.jersey.core', name: 'jersey-client', version: '2.0' - testLibrary group: 'org.jboss.resteasy', name: 'resteasy-client', version: '3.0.5.Final' - // ^ This version has timeouts https://issues.redhat.com/browse/RESTEASY-975 - testLibrary group: 'org.apache.cxf', name: 'cxf-rt-rs-client', version: '3.1.0' - // Doesn't work with CXF 3.0.x because their context is wrong: - // https://github.com/apache/cxf/commit/335c7bad2436f08d6d54180212df5a52157c9f21 - - testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3' - - testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-4.0') - - latestDepTestLibrary group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.27' - latestDepTestLibrary group: 'org.glassfish.jersey.core', name: 'jersey-client', version: '2.27' - latestDepTestLibrary group: 'org.apache.cxf', name: 'cxf-rt-rs-client', version: '3.2.6' - latestDepTestLibrary group: 'org.jboss.resteasy', name: 'resteasy-client', version: '3.0.26.Final' -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ClientTracingFeature.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ClientTracingFeature.java deleted file mode 100644 index 2408ac92a5..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ClientTracingFeature.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import javax.ws.rs.core.Feature; -import javax.ws.rs.core.FeatureContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ClientTracingFeature implements Feature { - - private static final Logger log = LoggerFactory.getLogger(ClientTracingFeature.class); - - @Override - public boolean configure(FeatureContext context) { - context.register(new ClientTracingFilter()); - log.debug("ClientTracingFilter registered"); - return true; - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ClientTracingFilter.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ClientTracingFilter.java deleted file mode 100644 index 83c36725a9..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ClientTracingFilter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.JaxRsClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import javax.annotation.Priority; -import javax.ws.rs.Priorities; -import javax.ws.rs.client.ClientRequestContext; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.ClientResponseContext; -import javax.ws.rs.client.ClientResponseFilter; - -@Priority(Priorities.HEADER_DECORATOR) -public class ClientTracingFilter implements ClientRequestFilter, ClientResponseFilter { - public static final String SPAN_PROPERTY_NAME = "io.opentelemetry.auto.jax-rs-client.span"; - - @Override - public void filter(ClientRequestContext requestContext) { - Span span = tracer().startSpan(requestContext); - // TODO (trask) expose inject separate from startScope, e.g. for async cases - Scope scope = tracer().startScope(span, requestContext); - scope.close(); - requestContext.setProperty(SPAN_PROPERTY_NAME, span); - } - - @Override - public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) { - Object spanObj = requestContext.getProperty(SPAN_PROPERTY_NAME); - if (spanObj instanceof Span) { - Span span = (Span) spanObj; - tracer().end(span, responseContext); - } - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/InjectAdapter.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/InjectAdapter.java deleted file mode 100644 index b282052fd8..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/InjectAdapter.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import javax.ws.rs.client.ClientRequestContext; - -public final class InjectAdapter implements TextMapPropagator.Setter { - - public static final InjectAdapter SETTER = new InjectAdapter(); - - @Override - public void set(ClientRequestContext carrier, String key, String value) { - // Don't allow duplicates. - carrier.getHeaders().putSingle(key, value); - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JaxRsClientInstrumentationModule.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JaxRsClientInstrumentationModule.java deleted file mode 100644 index 7934174012..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JaxRsClientInstrumentationModule.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import javax.ws.rs.client.Client; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class JaxRsClientInstrumentationModule extends InstrumentationModule { - - public JaxRsClientInstrumentationModule() { - super("jaxrs-client", "jaxrs-client-2.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ClientBuilderInstrumentation()); - } - - public static class ClientBuilderInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.ws.rs.client.ClientBuilder"); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("javax.ws.rs.client.ClientBuilder")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("build").and(returns(hasInterface(named("javax.ws.rs.client.Client")))), - JaxRsClientInstrumentationModule.class.getName() + "$ClientBuilderAdvice"); - } - } - - public static class ClientBuilderAdvice { - - @Advice.OnMethodExit - public static void registerFeature( - @Advice.Return(typing = Assigner.Typing.DYNAMIC) Client client) { - // Register on the generated client instead of the builder - // The build() can be called multiple times and is not thread safe - // A client is only created once - client.register(ClientTracingFeature.class); - } - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JaxRsClientTracer.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JaxRsClientTracer.java deleted file mode 100644 index 4ec89ebaad..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JaxRsClientTracer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.InjectAdapter.SETTER; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import javax.ws.rs.client.ClientRequestContext; -import javax.ws.rs.client.ClientResponseContext; - -public class JaxRsClientTracer - extends HttpClientTracer { - private static final JaxRsClientTracer TRACER = new JaxRsClientTracer(); - - public static JaxRsClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(ClientRequestContext httpRequest) { - return httpRequest.getMethod(); - } - - @Override - protected URI url(ClientRequestContext httpRequest) { - return httpRequest.getUri(); - } - - @Override - protected Integer status(ClientResponseContext httpResponse) { - return httpResponse.getStatus(); - } - - @Override - protected String requestHeader(ClientRequestContext clientRequestContext, String name) { - return clientRequestContext.getHeaderString(name); - } - - @Override - protected String responseHeader(ClientResponseContext clientResponseContext, String name) { - return clientResponseContext.getHeaderString(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jaxrs-client"; - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxMultithreadedClientTest.groovy b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxMultithreadedClientTest.groovy deleted file mode 100644 index 4393c7dc13..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxMultithreadedClientTest.groovy +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.server.http.TestHttpServer.httpServer - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import javax.ws.rs.client.Client -import org.glassfish.jersey.client.JerseyClientBuilder -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.util.concurrent.AsyncConditions - -class JaxMultithreadedClientTest extends AgentTestRunner { - - @AutoCleanup - @Shared - def server = httpServer { - handlers { - prefix("success") { - String msg = "Hello." - response.status(200).send(msg) - } - } - } - - def "multiple threads using the same builder works"() { - given: - def conds = new AsyncConditions(10) - def uri = server.address.resolve("/success") - def builder = new JerseyClientBuilder() - - // Start 10 threads and do 50 requests each - when: - (1..10).each { - Thread.start { - boolean hadErrors = (1..50).any { - try { - Client client = builder.build() - client.target(uri).request().get() - } catch (Exception e) { - e.printStackTrace() - return true - } - return false - } - - conds.evaluate { - assert !hadErrors - } - } - } - - then: - conds.await(30) - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxRsClientAsyncTest.groovy b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxRsClientAsyncTest.groovy deleted file mode 100644 index dfc2c7fd17..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxRsClientAsyncTest.groovy +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit -import javax.ws.rs.client.AsyncInvoker -import javax.ws.rs.client.Client -import javax.ws.rs.client.ClientBuilder -import javax.ws.rs.client.Entity -import javax.ws.rs.client.InvocationCallback -import javax.ws.rs.client.WebTarget -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import org.apache.cxf.jaxrs.client.spec.ClientBuilderImpl -import org.glassfish.jersey.client.ClientConfig -import org.glassfish.jersey.client.ClientProperties -import org.glassfish.jersey.client.JerseyClientBuilder -import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder -import spock.lang.Timeout - -abstract class JaxRsClientAsyncTest extends HttpClientTest { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Client client = builder().build() - WebTarget service = client.target(uri) - def builder = service.request(MediaType.TEXT_PLAIN) - headers.each { builder.header(it.key, it.value) } - AsyncInvoker request = builder.async() - - def body = BODY_METHODS.contains(method) ? Entity.text("") : null - def latch = new CountDownLatch(1) - Response response = request.method(method, (Entity) body, new InvocationCallback() { - @Override - void completed(Response s) { - callback?.call() - latch.countDown() - } - - @Override - void failed(Throwable throwable) { - latch.countDown() - } - }).get() - response.close() - - // need to wait for callback to complete in case test is expecting span from it - latch.await() - return response.status - } - - abstract ClientBuilder builder() -} - -@Timeout(5) -class JerseyClientAsyncTest extends JaxRsClientAsyncTest { - - @Override - ClientBuilder builder() { - ClientConfig config = new ClientConfig() - config.property(ClientProperties.CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS) - return new JerseyClientBuilder().withConfig(config) - } - - boolean testCircularRedirects() { - false - } -} - -@Timeout(5) -class ResteasyClientAsyncTest extends JaxRsClientAsyncTest { - - @Override - ClientBuilder builder() { - return new ResteasyClientBuilder() - .establishConnectionTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS) - } - - boolean testRedirects() { - false - } -} - -@Timeout(5) -class CxfClientAsyncTest extends JaxRsClientAsyncTest { - - @Override - ClientBuilder builder() { - return new ClientBuilderImpl() - } - - boolean testRedirects() { - false - } - - boolean testConnectionFailure() { - false - } - - boolean testRemoteConnection() { - // FIXME: span not reported correctly. - false - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxRsClientTest.groovy b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxRsClientTest.groovy deleted file mode 100644 index 7c940fc03f..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/JaxRsClientTest.groovy +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.TimeUnit -import javax.ws.rs.client.Client -import javax.ws.rs.client.ClientBuilder -import javax.ws.rs.client.Entity -import javax.ws.rs.client.Invocation -import javax.ws.rs.client.WebTarget -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response -import org.apache.cxf.jaxrs.client.spec.ClientBuilderImpl -import org.glassfish.jersey.client.ClientConfig -import org.glassfish.jersey.client.ClientProperties -import org.glassfish.jersey.client.JerseyClientBuilder -import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder -import spock.lang.Timeout -import spock.lang.Unroll - -abstract class JaxRsClientTest extends HttpClientTest { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - - Client client = builder().build() - WebTarget service = client.target(uri) - Invocation.Builder request = service.request(MediaType.TEXT_PLAIN) - headers.each { request.header(it.key, it.value) } - def body = BODY_METHODS.contains(method) ? Entity.text("") : null - Response response = request.method(method, (Entity) body) - callback?.call() - - return response.status - } - - abstract ClientBuilder builder() - - @Unroll - def "should properly convert HTTP status #statusCode to span error status"() { - given: - def method = "GET" - def uri = server.address.resolve(path) - - when: - def actualStatusCode = doRequest(method, uri) - - then: - assert actualStatusCode == statusCode - - assertTraces(1) { - trace(0, 2) { - span(0) { - hasNoParent() - name expectedOperationName(method) - kind CLIENT - errored true - attributes { - "${SemanticAttributes.NET_TRANSPORT.key()}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key()}" uri.host - "${SemanticAttributes.NET_PEER_IP.key()}" { it == null || it == "127.0.0.1" } - "${SemanticAttributes.NET_PEER_PORT.key()}" uri.port > 0 ? uri.port : { it == null || it == 443 } - "${SemanticAttributes.HTTP_URL.key()}" "${uri}" - "${SemanticAttributes.HTTP_METHOD.key()}" method - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" statusCode - "${SemanticAttributes.HTTP_FLAVOR.key()}" "1.1" - } - } - serverSpan(it, 1, span(0)) - } - } - - where: - path | statusCode - "/client-error" | 400 - "/error" | 500 - } -} - -@Timeout(5) -class JerseyClientTest extends JaxRsClientTest { - - @Override - ClientBuilder builder() { - ClientConfig config = new ClientConfig() - config.property(ClientProperties.CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS) - return new JerseyClientBuilder().withConfig(config) - } - - boolean testCircularRedirects() { - false - } -} - -@Timeout(5) -class ResteasyClientTest extends JaxRsClientTest { - - @Override - ClientBuilder builder() { - return new ResteasyClientBuilder() - .establishConnectionTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS) - } - - boolean testRedirects() { - false - } -} - -@Timeout(5) -class CxfClientTest extends JaxRsClientTest { - - @Override - ClientBuilder builder() { - return new ClientBuilderImpl() -// .property(ClientImpl.HTTP_CONNECTION_TIMEOUT_PROP, (long) CONNECT_TIMEOUT_MS) -// .property(ClientImpl.HTTP_RECEIVE_TIMEOUT_PROP, (long) READ_TIMEOUT_MS) - } - - boolean testRedirects() { - false - } - - boolean testConnectionFailure() { - false - } - - boolean testRemoteConnection() { - // FIXME: span not reported correctly. - false - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/ResteasyProxyClientTest.groovy b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/ResteasyProxyClientTest.groovy deleted file mode 100644 index e859b15db1..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-common/src/test/groovy/ResteasyProxyClientTest.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.nio.charset.StandardCharsets -import javax.ws.rs.GET -import javax.ws.rs.HeaderParam -import javax.ws.rs.POST -import javax.ws.rs.PUT -import javax.ws.rs.Path -import javax.ws.rs.QueryParam -import javax.ws.rs.core.Response -import org.apache.http.client.utils.URLEncodedUtils -import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder -import org.jboss.resteasy.specimpl.ResteasyUriBuilder - -class ResteasyProxyClientTest extends HttpClientTest { - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def proxyMethodName = "${method}_${uri.path}".toLowerCase() - .replace("/", "") - .replace('-', '_') - - def param = URLEncodedUtils.parse(uri, StandardCharsets.UTF_8.name()) - .stream().findFirst() - .map({ it.value }) - .orElse(null) - - def isTestServer = headers.get("is-test-server") - - def proxy = new ResteasyClientBuilder() - .build() - .target(new ResteasyUriBuilder().uri(server.address)) - .proxy(ResteasyProxyResource) - - def response = proxy."$proxyMethodName"(param, isTestServer) - - callback?.call() - - return response.status - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - false - } -} - -@Path("") -interface ResteasyProxyResource { - @GET - @Path("success") - Response get_success(@QueryParam("with") String param, - @HeaderParam("is-test-server") String isTestServer) - - @POST - @Path("success") - Response post_success(@QueryParam("with") String param, - @HeaderParam("is-test-server") String isTestServer) - - @PUT - @Path("success") - Response put_success(@QueryParam("with") String param, - @HeaderParam("is-test-server") String isTestServer) -} \ No newline at end of file diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-jersey-2.0/jaxrs-client-2.0-jersey-2.0.gradle b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-jersey-2.0/jaxrs-client-2.0-jersey-2.0.gradle deleted file mode 100644 index 643f5d4680..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-jersey-2.0/jaxrs-client-2.0-jersey-2.0.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.glassfish.jersey.core" - module = "jersey-client" - versions = "[2.0,)" - } -} - -dependencies { - compileOnly group: 'org.glassfish.jersey.core', name: 'jersey-client', version: '2.0' - - implementation project(':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-common') -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JerseyClientInstrumentationModule.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JerseyClientInstrumentationModule.java deleted file mode 100644 index 2af2fc7781..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/JerseyClientInstrumentationModule.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.JaxRsClientTracer.tracer; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.glassfish.jersey.client.ClientRequest; - -/** - * JAX-RS Client API doesn't define a good point where we can handle connection failures, so we must - * handle these errors at the implementation level. - */ -@AutoService(InstrumentationModule.class) -public class JerseyClientInstrumentationModule extends InstrumentationModule { - - public JerseyClientInstrumentationModule() { - super("jaxrs-client", "jaxrs-client-2.0", "jersey-client", "jersey-client-2.0"); - } - - @Override - public List typeInstrumentations() { - return Collections.singletonList(new JerseyClientConnectionErrorInstrumentation()); - } - - public static class JerseyClientConnectionErrorInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.glassfish.jersey.client.JerseyInvocation"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - - transformers.put( - isMethod().and(isPublic()).and(named("invoke")), - JerseyClientInstrumentationModule.class.getName() + "$InvokeAdvice"); - - transformers.put( - isMethod().and(isPublic()).and(named("submit")).and(returns(Future.class)), - JerseyClientInstrumentationModule.class.getName() + "$SubmitAdvice"); - - return transformers; - } - } - - public static class InvokeAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void handleError( - @Advice.FieldValue("requestContext") ClientRequest context, - @Advice.Thrown Throwable throwable) { - if (throwable != null) { - Object prop = context.getProperty(ClientTracingFilter.SPAN_PROPERTY_NAME); - if (prop instanceof Span) { - tracer().endExceptionally((Span) prop, throwable); - } - } - } - } - - public static class SubmitAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void handleError( - @Advice.FieldValue("requestContext") ClientRequest context, - @Advice.Return(readOnly = false) Future future) { - if (!(future instanceof WrappedFuture)) { - future = new WrappedFuture<>(future, context); - } - } - } - - public static class WrappedFuture implements Future { - - private final Future wrapped; - private final ClientRequest context; - - public WrappedFuture(Future wrapped, ClientRequest context) { - this.wrapped = wrapped; - this.context = context; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return wrapped.cancel(mayInterruptIfRunning); - } - - @Override - public boolean isCancelled() { - return wrapped.isCancelled(); - } - - @Override - public boolean isDone() { - return wrapped.isDone(); - } - - @Override - public T get() throws InterruptedException, ExecutionException { - try { - return wrapped.get(); - } catch (ExecutionException e) { - Object prop = context.getProperty(ClientTracingFilter.SPAN_PROPERTY_NAME); - if (prop instanceof Span) { - tracer().endExceptionally((Span) prop, e.getCause()); - } - throw e; - } - } - - @Override - public T get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - try { - return wrapped.get(timeout, unit); - } catch (ExecutionException e) { - Object prop = context.getProperty(ClientTracingFilter.SPAN_PROPERTY_NAME); - if (prop instanceof Span) { - tracer().endExceptionally((Span) prop, e.getCause()); - } - throw e; - } - } - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/jaxrs-client-2.0-resteasy-2.0.gradle b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/jaxrs-client-2.0-resteasy-2.0.gradle deleted file mode 100644 index 24bc78799e..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/jaxrs-client-2.0-resteasy-2.0.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.jboss.resteasy" - module = "resteasy-client" - versions = "[2.0,)" - } -} - -dependencies { - compileOnly group: 'org.jboss.resteasy', name: 'resteasy-client', version: '3.0.0.Final' - - implementation project(':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-common') -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyClientInstrumentationModule.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyClientInstrumentationModule.java deleted file mode 100644 index c23841f685..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyClientInstrumentationModule.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.ResteasyClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import javax.ws.rs.core.Response; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.jboss.resteasy.client.jaxrs.internal.ClientInvocation; - -/** - * Unlike other supported JAX-RS Client implementations, Resteasy's one is very simple and passes - * all requests through single point. Both sync ADN async! This allows for easy instrumentation and - * proper scope handling. - * - *

This specific instrumentation will not conflict with {@link JaxRsClientInstrumentationModule}, - * because {@link JaxRsClientTracer} used by the latter checks against double client spans. - */ -@AutoService(InstrumentationModule.class) -public class ResteasyClientInstrumentationModule extends InstrumentationModule { - - public ResteasyClientInstrumentationModule() { - super("jaxrs-client", "jaxrs-client-2.0", "resteasy-client", "resteasy-client-2.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ResteasyClientConnectionErrorInstrumentation()); - } - - private static final class ResteasyClientConnectionErrorInstrumentation - implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.jboss.resteasy.client.jaxrs.internal.ClientInvocation"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("invoke")).and(takesArguments(0)), - ResteasyClientInstrumentationModule.class.getName() + "$InvokeAdvice"); - } - } - - public static class InvokeAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.This ClientInvocation invocation, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(invocation); - scope = tracer().startScope(span, invocation); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return Response response, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span, response); - } - } - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyClientTracer.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyClientTracer.java deleted file mode 100644 index 39be1ba03e..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyClientTracer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0.ResteasyInjectAdapter.SETTER; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import javax.ws.rs.core.Response; -import org.jboss.resteasy.client.jaxrs.internal.ClientInvocation; - -public class ResteasyClientTracer - extends HttpClientTracer { - private static final ResteasyClientTracer TRACER = new ResteasyClientTracer(); - - public static ResteasyClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(ClientInvocation httpRequest) { - return httpRequest.getMethod(); - } - - @Override - protected URI url(ClientInvocation httpRequest) { - return httpRequest.getUri(); - } - - @Override - protected Integer status(Response httpResponse) { - return httpResponse.getStatus(); - } - - @Override - protected String requestHeader(ClientInvocation clientRequestContext, String name) { - return clientRequestContext.getHeaders().getHeader(name); - } - - @Override - protected String responseHeader(Response httpResponse, String name) { - return httpResponse.getHeaderString(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jaxrs-client"; - } -} diff --git a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyInjectAdapter.java b/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyInjectAdapter.java deleted file mode 100644 index 4492978d66..0000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-2.0/jaxrs-client-2.0-resteasy-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v2_0/ResteasyInjectAdapter.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v2_0; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.jboss.resteasy.client.jaxrs.internal.ClientInvocation; - -public final class ResteasyInjectAdapter implements TextMapPropagator.Setter { - - public static final ResteasyInjectAdapter SETTER = new ResteasyInjectAdapter(); - - @Override - public void set(ClientInvocation carrier, String key, String value) { - // Don't allow duplicates. - carrier.getHeaders().header(key, value); - } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/javaagent/src/test/groovy/JerseyTest.groovy b/instrumentation/jaxrs/jaxrs-1.0/javaagent/src/test/groovy/JerseyTest.groovy index 2b5746c1f2..4d5ab227a8 100644 --- a/instrumentation/jaxrs/jaxrs-1.0/javaagent/src/test/groovy/JerseyTest.groovy +++ b/instrumentation/jaxrs/jaxrs-1.0/javaagent/src/test/groovy/JerseyTest.groovy @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace import static io.opentelemetry.api.trace.Span.Kind.INTERNAL +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace import io.dropwizard.testing.junit.ResourceTestRule import io.opentelemetry.instrumentation.test.AgentTestRunner diff --git a/instrumentation/jaxrs/jaxrs-1.0/jaxrs-1.0.gradle b/instrumentation/jaxrs/jaxrs-1.0/jaxrs-1.0.gradle deleted file mode 100644 index e8d66fa759..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/jaxrs-1.0.gradle +++ /dev/null @@ -1,21 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "javax.ws.rs" - module = "jsr311-api" - versions = "[0.5,)" - } - fail { - group = "javax.ws.rs" - module = "javax.ws.rs-api" - versions = "[,]" - } -} - -dependencies { - compileOnly group: 'javax.ws.rs', name: 'jsr311-api', version: '1.1.1' - - testImplementation group: 'io.dropwizard', name: 'dropwizard-testing', version: '0.7.1' - testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3' -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsAnnotationsInstrumentation.java b/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsAnnotationsInstrumentation.java deleted file mode 100644 index 611d1bd92a..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsAnnotationsInstrumentation.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v1_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v1_0.JaxRsAnnotationsTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasSuperMethod; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.util.Map; -import javax.ws.rs.Path; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JaxRsAnnotationsInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.ws.rs.Path"); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - isAnnotatedWith(named("javax.ws.rs.Path")) - .or(declaresMethod(isAnnotatedWith(named("javax.ws.rs.Path"))))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and( - hasSuperMethod( - isAnnotatedWith( - namedOneOf( - "javax.ws.rs.Path", - "javax.ws.rs.DELETE", - "javax.ws.rs.GET", - "javax.ws.rs.HEAD", - "javax.ws.rs.OPTIONS", - "javax.ws.rs.POST", - "javax.ws.rs.PUT")))), - JaxRsAnnotationsInstrumentation.class.getName() + "$JaxRsAnnotationsAdvice"); - } - - public static class JaxRsAnnotationsAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope nameSpan(@Advice.This Object target, @Advice.Origin Method method) { - if (CallDepthThreadLocalMap.incrementCallDepth(Path.class) > 0) { - return null; - } - - Span span = tracer().startSpan(target.getClass(), method); - - return new SpanWithScope(span, span.makeCurrent()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Enter SpanWithScope spanWithScope, @Advice.Thrown Throwable throwable) { - if (spanWithScope == null) { - return; - } - CallDepthThreadLocalMap.reset(Path.class); - - Span span = spanWithScope.getSpan(); - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - spanWithScope.closeScope(); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsAnnotationsTracer.java b/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsAnnotationsTracer.java deleted file mode 100644 index 348c93ba33..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsAnnotationsTracer.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v1_0; - -import static io.opentelemetry.javaagent.instrumentation.api.WeakMap.Provider.newWeakMap; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.servlet.ServletContextPath; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.WeakMap; -import io.opentelemetry.javaagent.tooling.ClassHierarchyIterable; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.Path; - -public class JaxRsAnnotationsTracer extends BaseTracer { - - private static final JaxRsAnnotationsTracer TRACER = new JaxRsAnnotationsTracer(); - - public static JaxRsAnnotationsTracer tracer() { - return TRACER; - } - - private final WeakMap, Map> spanNames = newWeakMap(); - - public Span startSpan(Class target, Method method) { - String pathBasedSpanName = getPathSpanName(target, method); - Context context = Context.current(); - Span serverSpan = BaseTracer.getCurrentServerSpan(context); - - // When jax-rs is the root, we want to name using the path, otherwise use the class/method. - String spanName; - if (serverSpan == null) { - spanName = pathBasedSpanName; - } else { - spanName = spanNameForMethod(target, method); - updateServerSpanName(context, serverSpan, pathBasedSpanName); - } - - return tracer.spanBuilder(spanName).startSpan(); - } - - private void updateServerSpanName(Context context, Span span, String spanName) { - if (!spanName.isEmpty()) { - span.updateName(ServletContextPath.prepend(context, spanName)); - } - } - - /** - * Returns the span name given a JaxRS annotated method. Results are cached so this method can be - * called multiple times without significantly impacting performance. - * - * @return The result can be an empty string but will never be {@code null}. - */ - private String getPathSpanName(Class target, Method method) { - Map classMap = spanNames.get(target); - - if (classMap == null) { - spanNames.putIfAbsent(target, new ConcurrentHashMap<>()); - classMap = spanNames.get(target); - // classMap should not be null at this point because we have a - // strong reference to target and don't manually clear the map. - } - - String spanName = classMap.get(method); - if (spanName == null) { - String httpMethod = null; - Path methodPath = null; - Path classPath = findClassPath(target); - for (Class currentClass : new ClassHierarchyIterable(target)) { - Method currentMethod; - if (currentClass.equals(target)) { - currentMethod = method; - } else { - currentMethod = findMatchingMethod(method, currentClass.getDeclaredMethods()); - } - - if (currentMethod != null) { - if (httpMethod == null) { - httpMethod = locateHttpMethod(currentMethod); - } - if (methodPath == null) { - methodPath = findMethodPath(currentMethod); - } - - if (httpMethod != null && methodPath != null) { - break; - } - } - } - spanName = buildSpanName(classPath, methodPath); - classMap.put(method, spanName); - } - - return spanName; - } - - private String locateHttpMethod(Method method) { - String httpMethod = null; - for (Annotation ann : method.getDeclaredAnnotations()) { - if (ann.annotationType().getAnnotation(HttpMethod.class) != null) { - httpMethod = ann.annotationType().getSimpleName(); - } - } - return httpMethod; - } - - private Path findMethodPath(Method method) { - return method.getAnnotation(Path.class); - } - - private Path findClassPath(Class target) { - for (Class currentClass : new ClassHierarchyIterable(target)) { - Path annotation = currentClass.getAnnotation(Path.class); - if (annotation != null) { - // Annotation overridden, no need to continue. - return annotation; - } - } - - return null; - } - - private Method findMatchingMethod(Method baseMethod, Method[] methods) { - nextMethod: - for (Method method : methods) { - if (!baseMethod.getReturnType().equals(method.getReturnType())) { - continue; - } - - if (!baseMethod.getName().equals(method.getName())) { - continue; - } - - Class[] baseParameterTypes = baseMethod.getParameterTypes(); - Class[] parameterTypes = method.getParameterTypes(); - if (baseParameterTypes.length != parameterTypes.length) { - continue; - } - for (int i = 0; i < baseParameterTypes.length; i++) { - if (!baseParameterTypes[i].equals(parameterTypes[i])) { - continue nextMethod; - } - } - return method; - } - return null; - } - - private String buildSpanName(Path classPath, Path methodPath) { - String spanName; - StringBuilder spanNameBuilder = new StringBuilder(); - boolean skipSlash = false; - if (classPath != null) { - if (!classPath.value().startsWith("/")) { - spanNameBuilder.append("/"); - } - spanNameBuilder.append(classPath.value()); - skipSlash = classPath.value().endsWith("/"); - } - - if (methodPath != null) { - String path = methodPath.value(); - if (skipSlash) { - if (path.startsWith("/")) { - path = path.length() == 1 ? "" : path.substring(1); - } - } else if (!path.startsWith("/")) { - spanNameBuilder.append("/"); - } - spanNameBuilder.append(path); - } - - spanName = spanNameBuilder.toString().trim(); - return spanName; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jaxrs"; - } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsInstrumentationModule.java b/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsInstrumentationModule.java deleted file mode 100644 index 5a8054c894..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v1_0/JaxRsInstrumentationModule.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v1_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class JaxRsInstrumentationModule extends InstrumentationModule { - public JaxRsInstrumentationModule() { - super("jaxrs", "jaxrs-1.0"); - } - - // this is required to make sure instrumentation won't apply to jax-rs 2 - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return not(hasClassesNamed("javax.ws.rs.container.AsyncResponse")); - } - - @Override - public List typeInstrumentations() { - return singletonList(new JaxRsAnnotationsInstrumentation()); - } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/test/groovy/JaxRsAnnotations1InstrumentationTest.groovy b/instrumentation/jaxrs/jaxrs-1.0/src/test/groovy/JaxRsAnnotations1InstrumentationTest.groovy deleted file mode 100644 index 47753308eb..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/test/groovy/JaxRsAnnotations1InstrumentationTest.groovy +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.javaagent.instrumentation.api.WeakMap -import io.opentelemetry.javaagent.instrumentation.jaxrs.v1_0.JaxRsAnnotationsTracer -import java.lang.reflect.Method -import javax.ws.rs.DELETE -import javax.ws.rs.GET -import javax.ws.rs.HEAD -import javax.ws.rs.OPTIONS -import javax.ws.rs.POST -import javax.ws.rs.PUT -import javax.ws.rs.Path - -class JaxRsAnnotations1InstrumentationTest extends AgentTestRunner { - - def "instrumentation can be used as root span and resource is set to METHOD PATH"() { - setup: - new Jax() { - @POST - @Path("/a") - void call() { - } - }.call() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "/a" - attributes { - } - } - } - } - } - - def "span named '#name' from annotations on class when is not root span"() { - setup: - def startingCacheSize = spanNames.size() - runUnderServerTrace("test") { - obj.call() - } - - expect: - assertTraces(1) { - trace(0, 2) { - span(0) { - name paramName - hasNoParent() - attributes { - } - } - span(1) { - name "${className}.call" - childOf span(0) - attributes { - } - } - } - } - spanNames.size() == startingCacheSize + 1 - spanNames.get(obj.class).size() == 1 - - when: "multiple calls to the same method" - runUnderServerTrace("test") { - (1..10).each { - obj.call() - } - } - then: "doesn't increase the cache size" - spanNames.size() == startingCacheSize + 1 - spanNames.get(obj.class).size() == 1 - - where: - paramName | obj - "/a" | new Jax() { - @Path("/a") - void call() { - } - } - "/b" | new Jax() { - @GET - @Path("/b") - void call() { - } - } - "/interface/c" | new InterfaceWithPath() { - @POST - @Path("/c") - void call() { - } - } - "/interface" | new InterfaceWithPath() { - @HEAD - void call() { - } - } - "/abstract/d" | new AbstractClassWithPath() { - @POST - @Path("/d") - void call() { - } - } - "/abstract" | new AbstractClassWithPath() { - @PUT - void call() { - } - } - "/child/e" | new ChildClassWithPath() { - @OPTIONS - @Path("/e") - void call() { - } - } - "/child/call" | new ChildClassWithPath() { - @DELETE - void call() { - } - } - "/child/call" | new ChildClassWithPath() - "/child/call" | new JavaInterfaces.ChildClassOnInterface() - // TODO: uncomment when we drop support for Java 7 - // "/child/invoke" | new JavaInterfaces.DefaultChildClassOnInterface() - - className = getClassName(obj.class) - - // JavaInterfaces classes are loaded on a different classloader, so we need to find the right cache instance. - decorator = obj.class.classLoader.loadClass(JaxRsAnnotationsTracer.name).getMethod("tracer").invoke(null) - spanNames = (WeakMap>) decorator.spanNames - } - - def "no annotations has no effect"() { - setup: - runUnderServerTrace("test") { - obj.call() - } - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test" - attributes { - } - } - } - } - - where: - obj | _ - new Jax() { - void call() { - } - } | _ - } - - interface Jax { - void call() - } - - @Path("/interface") - interface InterfaceWithPath extends Jax { - @GET - void call() - } - - @Path("/abstract") - static abstract class AbstractClassWithPath implements Jax { - @PUT - abstract void call() - } - - @Path("child") - static class ChildClassWithPath extends AbstractClassWithPath { - @Path("call") - @POST - void call() { - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/test/groovy/JerseyTest.groovy b/instrumentation/jaxrs/jaxrs-1.0/src/test/groovy/JerseyTest.groovy deleted file mode 100644 index 4d5ab227a8..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/test/groovy/JerseyTest.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderServerTrace - -import io.dropwizard.testing.junit.ResourceTestRule -import io.opentelemetry.instrumentation.test.AgentTestRunner -import org.junit.ClassRule -import spock.lang.Shared - -class JerseyTest extends AgentTestRunner { - - @Shared - @ClassRule - ResourceTestRule resources = ResourceTestRule.builder() - .addResource(new Resource.Test1()) - .addResource(new Resource.Test2()) - .addResource(new Resource.Test3()) - .build() - - def "test #resource"() { - when: - // start a trace because the test doesn't go through any servlet or other instrumentation. - def response = runUnderServerTrace("test.span") { - resources.client().resource(resource).post(String) - } - - then: - response == expectedResponse - - assertTraces(1) { - trace(0, 2) { - span(0) { - name expectedSpanName - attributes { - } - } - - span(1) { - childOf span(0) - name controllerName - attributes { - } - } - } - } - - where: - resource | expectedSpanName | controllerName | expectedResponse - "/test/hello/bob" | "/test/hello/{name}" | "Test1.hello" | "Test1 bob!" - "/test2/hello/bob" | "/test2/hello/{name}" | "Test2.hello" | "Test2 bob!" - "/test3/hi/bob" | "/test3/hi/{name}" | "Test3.hello" | "Test3 bob!" - } - - def "test nested call"() { - - when: - // start a trace because the test doesn't go through any servlet or other instrumentation. - def response = runUnderServerTrace("test.span") { - resources.client().resource(resource).post(String) - } - - then: - response == expectedResponse - - assertTraces(1) { - trace(0, 2) { - span(0) { - name expectedSpanName - attributes { - } - } - span(1) { - childOf span(0) - name controller1Name - kind INTERNAL - attributes { - } - } - } - } - - where: - resource | expectedSpanName | controller1Name | expectedResponse - "/test3/nested" | "/test3/nested" | "Test3.nested" | "Test3 nested!" - } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/test/java/JavaInterfaces.java b/instrumentation/jaxrs/jaxrs-1.0/src/test/java/JavaInterfaces.java deleted file mode 100644 index 891d2b5f5d..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/test/java/JavaInterfaces.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import javax.ws.rs.GET; -import javax.ws.rs.Path; - -public class JavaInterfaces { - - interface Jax { - - void call(); - } - - @Path("interface") - interface InterfaceWithClassMethodPath extends Jax { - - @Override - @GET - @Path("invoke") - void call(); - } - - @Path("abstract") - abstract class AbstractClassOnInterfaceWithClassPath implements InterfaceWithClassMethodPath { - - @GET - @Path("call") - @Override - public void call() { - // do nothing - } - - abstract void actual(); - } - - @Path("child") - class ChildClassOnInterface extends AbstractClassOnInterfaceWithClassPath { - - @Override - void actual() { - // do nothing - } - } - - // TODO: uncomment when we drop support for Java 7 - // @Path("interface") - // interface DefaultInterfaceWithClassMethodPath extends Jax { - // - // @GET - // @Path("invoke") - // default void call() { - // actual(); - // } - // - // void actual(); - // } - // - // @Path("child") - // class DefaultChildClassOnInterface implements DefaultInterfaceWithClassMethodPath { - // - // @Override - // public void actual() { - // // do nothing - // } - // } -} diff --git a/instrumentation/jaxrs/jaxrs-1.0/src/test/java/Resource.java b/instrumentation/jaxrs/jaxrs-1.0/src/test/java/Resource.java deleted file mode 100644 index d962f172ca..0000000000 --- a/instrumentation/jaxrs/jaxrs-1.0/src/test/java/Resource.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; - -// Originally had this as a groovy class but was getting some weird errors. -@Path("/ignored") -public interface Resource { - @Path("ignored") - String hello(String name); - - @Path("/test") - interface SubResource extends Cloneable, Resource { - @Override - @POST - @Path("/hello/{name}") - String hello(@PathParam("name") String name); - } - - class Test1 implements SubResource { - @Override - public String hello(String name) { - return "Test1 " + name + "!"; - } - } - - @Path("/test2") - class Test2 implements SubResource { - @Override - public String hello(String name) { - return "Test2 " + name + "!"; - } - } - - @Path("/test3") - class Test3 implements SubResource { - @Override - @POST - @Path("/hi/{name}") - public String hello(@PathParam("name") String name) { - return "Test3 " + name + "!"; - } - - @POST - @Path("/nested") - public String nested() { - return hello("nested"); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/jaxrs-2.0-common.gradle b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/jaxrs-2.0-common.gradle deleted file mode 100644 index 83b2eb2a8c..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/jaxrs-2.0-common.gradle +++ /dev/null @@ -1,18 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - fail { - group = "javax.ws.rs" - module = "jsr311-api" - versions = "[,]" - } - pass { - group = "javax.ws.rs" - module = "javax.ws.rs-api" - versions = "[,]" - } -} - -dependencies { - compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0' -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/AbstractRequestContextInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/AbstractRequestContextInstrumentation.java deleted file mode 100644 index 110efec6f2..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/AbstractRequestContextInstrumentation.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public abstract class AbstractRequestContextInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.ws.rs.container.ContainerRequestContext"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.ws.rs.container.ContainerRequestContext")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("abortWith")) - .and(takesArguments(1)) - .and(takesArgument(0, named("javax.ws.rs.core.Response"))), - abortAdviceName()); - } - - protected abstract String abortAdviceName(); -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CompletionStageFinishCallback.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CompletionStageFinishCallback.java deleted file mode 100644 index ddfeafdb5d..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/CompletionStageFinishCallback.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import java.util.function.BiFunction; - -public class CompletionStageFinishCallback implements BiFunction { - private final Span span; - - public CompletionStageFinishCallback(Span span) { - this.span = span; - } - - @Override - public T apply(T result, Throwable throwable) { - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - return result; - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ContainerRequestFilterInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ContainerRequestFilterInstrumentation.java deleted file mode 100644 index 157da6e61a..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/ContainerRequestFilterInstrumentation.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * This adds the filter class name to the request properties. The class name is used by - * DefaultRequestContextInstrumentation - */ -public class ContainerRequestFilterInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.ws.rs.container.ContainerRequestFilter"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.ws.rs.container.ContainerRequestFilter")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("filter")) - .and(takesArguments(1)) - .and(takesArgument(0, named("javax.ws.rs.container.ContainerRequestContext"))), - ContainerRequestFilterInstrumentation.class.getName() + "$RequestFilterAdvice"); - } - - public static class RequestFilterAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void setFilterClass( - @Advice.This ContainerRequestFilter filter, - @Advice.Argument(0) ContainerRequestContext context) { - context.setProperty(JaxRsAnnotationsTracer.ABORT_FILTER_CLASS, filter.getClass()); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/DefaultRequestContextInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/DefaultRequestContextInstrumentation.java deleted file mode 100644 index 8097a44ec6..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/DefaultRequestContextInstrumentation.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import javax.ws.rs.container.ContainerRequestContext; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.asm.Advice.Local; - -/** - * Default context instrumentation. - * - *

JAX-RS does not define a way to get the matched resource method from the - * ContainerRequestContext - * - *

This default instrumentation uses the class name of the filter to create the span. More - * specific instrumentations may override this value. - */ -public class DefaultRequestContextInstrumentation extends AbstractRequestContextInstrumentation { - @Override - protected String abortAdviceName() { - return ContainerRequestContextAdvice.class.getName(); - } - - public static class ContainerRequestContextAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void createGenericSpan( - @Advice.This ContainerRequestContext context, - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope) { - if (context.getProperty(JaxRsAnnotationsTracer.ABORT_HANDLED) == null) { - Class filterClass = - (Class) context.getProperty(JaxRsAnnotationsTracer.ABORT_FILTER_CLASS); - Method method = null; - try { - method = filterClass.getMethod("filter", ContainerRequestContext.class); - } catch (NoSuchMethodException e) { - // Unable to find the filter method. This should not be reachable because the context - // can only be aborted inside the filter method - } - - span = tracer().startSpan(filterClass, method); - scope = tracer().startScope(span); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - RequestContextHelper.closeSpanAndScope(span, scope, throwable); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAnnotationsInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAnnotationsInstrumentation.java deleted file mode 100644 index def0c4f0d8..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAnnotationsInstrumentation.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasSuperMethod; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.CompletionStage; -import javax.ws.rs.Path; -import javax.ws.rs.container.AsyncResponse; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner.Typing; -import net.bytebuddy.matcher.ElementMatcher; - -public class JaxRsAnnotationsInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.ws.rs.Path"); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - isAnnotatedWith(named("javax.ws.rs.Path")) - .or(declaresMethod(isAnnotatedWith(named("javax.ws.rs.Path"))))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and( - hasSuperMethod( - isAnnotatedWith( - namedOneOf( - "javax.ws.rs.Path", - "javax.ws.rs.DELETE", - "javax.ws.rs.GET", - "javax.ws.rs.HEAD", - "javax.ws.rs.OPTIONS", - "javax.ws.rs.PATCH", - "javax.ws.rs.POST", - "javax.ws.rs.PUT")))), - JaxRsAnnotationsInstrumentation.class.getName() + "$JaxRsAnnotationsAdvice"); - } - - public static class JaxRsAnnotationsAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void nameSpan( - @Advice.This Object target, - @Advice.Origin Method method, - @Advice.AllArguments Object[] args, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelAsyncResponse") AsyncResponse asyncResponse) { - ContextStore contextStore = null; - for (Object arg : args) { - if (arg instanceof AsyncResponse) { - asyncResponse = (AsyncResponse) arg; - contextStore = InstrumentationContext.get(AsyncResponse.class, Span.class); - if (contextStore.get(asyncResponse) != null) { - /* - * We are probably in a recursive call and don't want to start a new span because it - * would replace the existing span in the asyncResponse and cause it to never finish. We - * could work around this by using a list instead, but we likely don't want the extra - * span anyway. - */ - return; - } - break; - } - } - - if (CallDepthThreadLocalMap.incrementCallDepth(Path.class) > 0) { - return; - } - - span = tracer().startSpan(target.getClass(), method); - - if (contextStore != null && asyncResponse != null) { - contextStore.put(asyncResponse, span); - } - - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Return(readOnly = false, typing = Typing.DYNAMIC) Object returnValue, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelAsyncResponse") AsyncResponse asyncResponse) { - if (span == null || scope == null) { - return; - } - CallDepthThreadLocalMap.reset(Path.class); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - scope.close(); - return; - } - - CompletionStage asyncReturnValue = - returnValue instanceof CompletionStage ? (CompletionStage) returnValue : null; - - if (asyncResponse != null && !asyncResponse.isSuspended()) { - // Clear span from the asyncResponse. Logically this should never happen. Added to be safe. - InstrumentationContext.get(AsyncResponse.class, Span.class).put(asyncResponse, null); - } - if (asyncReturnValue != null) { - // span finished by CompletionStageFinishCallback - asyncReturnValue = asyncReturnValue.handle(new CompletionStageFinishCallback<>(span)); - } - if ((asyncResponse == null || !asyncResponse.isSuspended()) && asyncReturnValue == null) { - tracer().end(span); - } - // else span finished by AsyncResponseAdvice - - scope.close(); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAnnotationsTracer.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAnnotationsTracer.java deleted file mode 100644 index 19986ce956..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAnnotationsTracer.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.api.WeakMap.Provider.newWeakMap; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.servlet.ServletContextPath; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.WeakMap; -import io.opentelemetry.javaagent.tooling.ClassHierarchyIterable; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.Path; - -public class JaxRsAnnotationsTracer extends BaseTracer { - public static final String ABORT_FILTER_CLASS = - "io.opentelemetry.javaagent.instrumentation.jaxrs2.filter.abort.class"; - public static final String ABORT_HANDLED = - "io.opentelemetry.javaagent.instrumentation.jaxrs2.filter.abort.handled"; - - private static final JaxRsAnnotationsTracer TRACER = new JaxRsAnnotationsTracer(); - - public static JaxRsAnnotationsTracer tracer() { - return TRACER; - } - - private final WeakMap, Map> spanNames = newWeakMap(); - - public Span startSpan(Class target, Method method) { - // We create span and immediately update its name - // We do that in order to reuse logic inside updateSpanNames method, which is used externally as - // well. - Context context = Context.current(); - Span span = tracer.spanBuilder("jax-rs.request").setParent(context).startSpan(); - updateSpanNames(context, span, BaseTracer.getCurrentServerSpan(context), target, method); - return span; - } - - public void updateSpanNames( - Context context, Span span, Span serverSpan, Class target, Method method) { - String pathBasedSpanName = ServletContextPath.prepend(context, getPathSpanName(target, method)); - if (serverSpan == null) { - updateSpanName(span, pathBasedSpanName); - } else { - updateSpanName(serverSpan, pathBasedSpanName); - updateSpanName(span, tracer().spanNameForMethod(target, method)); - } - } - - private void updateSpanName(Span span, String spanName) { - if (!spanName.isEmpty()) { - span.updateName(spanName); - } - } - - /** - * Returns the span name given a JaxRS annotated method. Results are cached so this method can be - * called multiple times without significantly impacting performance. - * - * @return The result can be an empty string but will never be {@code null}. - */ - private String getPathSpanName(Class target, Method method) { - Map classMap = spanNames.get(target); - - if (classMap == null) { - spanNames.putIfAbsent(target, new ConcurrentHashMap<>()); - classMap = spanNames.get(target); - // classMap should not be null at this point because we have a - // strong reference to target and don't manually clear the map. - } - - String spanName = classMap.get(method); - if (spanName == null) { - String httpMethod = null; - Path methodPath = null; - Path classPath = findClassPath(target); - for (Class currentClass : new ClassHierarchyIterable(target)) { - Method currentMethod; - if (currentClass.equals(target)) { - currentMethod = method; - } else { - currentMethod = findMatchingMethod(method, currentClass.getDeclaredMethods()); - } - - if (currentMethod != null) { - if (httpMethod == null) { - httpMethod = locateHttpMethod(currentMethod); - } - if (methodPath == null) { - methodPath = findMethodPath(currentMethod); - } - - if (httpMethod != null && methodPath != null) { - break; - } - } - } - spanName = buildSpanName(classPath, methodPath); - classMap.put(method, spanName); - } - - return spanName; - } - - private String locateHttpMethod(Method method) { - String httpMethod = null; - for (Annotation ann : method.getDeclaredAnnotations()) { - if (ann.annotationType().getAnnotation(HttpMethod.class) != null) { - httpMethod = ann.annotationType().getSimpleName(); - } - } - return httpMethod; - } - - private Path findMethodPath(Method method) { - return method.getAnnotation(Path.class); - } - - private Path findClassPath(Class target) { - for (Class currentClass : new ClassHierarchyIterable(target)) { - Path annotation = currentClass.getAnnotation(Path.class); - if (annotation != null) { - // Annotation overridden, no need to continue. - return annotation; - } - } - - return null; - } - - private Method findMatchingMethod(Method baseMethod, Method[] methods) { - nextMethod: - for (Method method : methods) { - if (!baseMethod.getReturnType().equals(method.getReturnType())) { - continue; - } - - if (!baseMethod.getName().equals(method.getName())) { - continue; - } - - Class[] baseParameterTypes = baseMethod.getParameterTypes(); - Class[] parameterTypes = method.getParameterTypes(); - if (baseParameterTypes.length != parameterTypes.length) { - continue; - } - for (int i = 0; i < baseParameterTypes.length; i++) { - if (!baseParameterTypes[i].equals(parameterTypes[i])) { - continue nextMethod; - } - } - return method; - } - return null; - } - - private String buildSpanName(Path classPath, Path methodPath) { - String spanName; - StringBuilder spanNameBuilder = new StringBuilder(); - boolean skipSlash = false; - if (classPath != null) { - String classPathValue = classPath.value(); - if (!classPathValue.startsWith("/")) { - spanNameBuilder.append("/"); - } - spanNameBuilder.append(classPathValue); - skipSlash = classPathValue.endsWith("/") || classPathValue.isEmpty(); - } - - if (methodPath != null) { - String path = methodPath.value(); - if (skipSlash) { - if (path.startsWith("/")) { - path = path.length() == 1 ? "" : path.substring(1); - } - } else if (!path.startsWith("/")) { - spanNameBuilder.append("/"); - } - spanNameBuilder.append(path); - } - - spanName = spanNameBuilder.toString().trim(); - - return spanName; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jaxrs"; - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAsyncResponseInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAsyncResponseInstrumentation.java deleted file mode 100644 index 0f47ce7d89..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsAsyncResponseInstrumentation.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import javax.ws.rs.container.AsyncResponse; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JaxRsAsyncResponseInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.ws.rs.container.AsyncResponse"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.ws.rs.container.AsyncResponse")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("resume").and(takesArgument(0, Object.class)).and(isPublic()), - JaxRsAsyncResponseInstrumentation.class.getName() + "$AsyncResponseAdvice"); - transformers.put( - named("resume").and(takesArgument(0, Throwable.class)).and(isPublic()), - JaxRsAsyncResponseInstrumentation.class.getName() + "$AsyncResponseThrowableAdvice"); - transformers.put( - named("cancel"), - JaxRsAsyncResponseInstrumentation.class.getName() + "$AsyncResponseCancelAdvice"); - return transformers; - } - - public static class AsyncResponseAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void stopSpan(@Advice.This AsyncResponse asyncResponse) { - - ContextStore contextStore = - InstrumentationContext.get(AsyncResponse.class, Span.class); - - Span span = contextStore.get(asyncResponse); - if (span != null) { - contextStore.put(asyncResponse, null); - tracer().end(span); - } - } - } - - public static class AsyncResponseThrowableAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void stopSpan( - @Advice.This AsyncResponse asyncResponse, @Advice.Argument(0) Throwable throwable) { - - ContextStore contextStore = - InstrumentationContext.get(AsyncResponse.class, Span.class); - - Span span = contextStore.get(asyncResponse); - if (span != null) { - contextStore.put(asyncResponse, null); - tracer().endExceptionally(span, throwable); - } - } - } - - public static class AsyncResponseCancelAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void stopSpan(@Advice.This AsyncResponse asyncResponse) { - - ContextStore contextStore = - InstrumentationContext.get(AsyncResponse.class, Span.class); - - Span span = contextStore.get(asyncResponse); - if (span != null) { - contextStore.put(asyncResponse, null); - span.setAttribute("canceled", true); - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java deleted file mode 100644 index 694d0d9941..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class JaxRsInstrumentationModule extends InstrumentationModule { - public JaxRsInstrumentationModule() { - super("jaxrs", "jaxrs-2.0"); - } - - // require jax-rs 2 - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return hasClassesNamed("javax.ws.rs.container.AsyncResponse"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ContainerRequestFilterInstrumentation(), - new DefaultRequestContextInstrumentation(), - new JaxRsAnnotationsInstrumentation(), - new JaxRsAsyncResponseInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap("javax.ws.rs.container.AsyncResponse", Span.class.getName()); - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/RequestContextHelper.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/RequestContextHelper.java deleted file mode 100644 index eeefec4b1d..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/RequestContextHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import java.lang.reflect.Method; -import javax.ws.rs.container.ContainerRequestContext; - -public final class RequestContextHelper { - public static Span createOrUpdateAbortSpan( - ContainerRequestContext requestContext, Class resourceClass, Method method) { - - if (method != null && resourceClass != null) { - requestContext.setProperty(JaxRsAnnotationsTracer.ABORT_HANDLED, true); - Context context = Java8BytecodeBridge.currentContext(); - Span serverSpan = BaseTracer.getCurrentServerSpan(context); - Span currentSpan = Java8BytecodeBridge.spanFromContext(context); - - // if there's no current span or it's the same as the server (servlet) span we need to start - // a JAX-RS one - // in other case, DefaultRequestContextInstrumentation must have already run so it's enough - // to just update the names - if (currentSpan == null || currentSpan == serverSpan) { - return tracer().startSpan(resourceClass, method); - } else { - tracer().updateSpanNames(context, currentSpan, serverSpan, resourceClass, method); - } - } - return null; - } - - public static void closeSpanAndScope(Span span, Scope scope, Throwable throwable) { - if (span == null || scope == null) { - return; - } - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - - scope.close(); - } - - private RequestContextHelper() {} -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/jaxrs-2.0-jersey-2.0.gradle b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/jaxrs-2.0-jersey-2.0.gradle deleted file mode 100644 index a03d297718..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/jaxrs-2.0-jersey-2.0.gradle +++ /dev/null @@ -1,30 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - // Cant assert fails because muzzle assumes all instrumentations will fail - // Instrumentations in jaxrs-2.0-common will pass - pass { - group = "org.glassfish.jersey.core" - module = "jersey-server" - versions = "[2.0,]" - } -} - -dependencies { - compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0' - compileOnly group: 'org.glassfish.jersey.core', name: 'jersey-server', version: '2.0' - - implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common') - - testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') - testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing') - - // First version with DropwizardTestSupport: - testLibrary group: 'io.dropwizard', name: 'dropwizard-testing', version: '0.8.0' - testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3' - testImplementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-afterburner', version: '2.9.10' -} - -test { - systemProperty 'testLatestDeps', testLatestDeps -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyInstrumentationModule.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyInstrumentationModule.java deleted file mode 100644 index d40f4e8cc3..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyInstrumentationModule.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class JerseyInstrumentationModule extends InstrumentationModule { - public JerseyInstrumentationModule() { - super("jaxrs", "jaxrs-2.0", "jersey", "jersey-2.0"); - } - - @Override - public List typeInstrumentations() { - return Collections.singletonList(new JerseyRequestContextInstrumentation()); - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyRequestContextInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyRequestContextInstrumentation.java deleted file mode 100644 index 7944446dc9..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JerseyRequestContextInstrumentation.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ResourceInfo; -import javax.ws.rs.core.UriInfo; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.asm.Advice.Local; - -/** - * Jersey specific context instrumentation. - * - *

JAX-RS does not define a way to get the matched resource method from the - * ContainerRequestContext - * - *

In the Jersey implementation, UriInfo implements ResourceInfo. The - * matched resource method can be retrieved from that object - */ -public class JerseyRequestContextInstrumentation extends AbstractRequestContextInstrumentation { - @Override - protected String abortAdviceName() { - return ContainerRequestContextAdvice.class.getName(); - } - - public static class ContainerRequestContextAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void decorateAbortSpan( - @Advice.This ContainerRequestContext context, - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope) { - UriInfo uriInfo = context.getUriInfo(); - - if (context.getProperty(JaxRsAnnotationsTracer.ABORT_HANDLED) == null - && uriInfo instanceof ResourceInfo) { - - ResourceInfo resourceInfo = (ResourceInfo) uriInfo; - Method method = resourceInfo.getResourceMethod(); - Class resourceClass = resourceInfo.getResourceClass(); - - span = RequestContextHelper.createOrUpdateAbortSpan(context, resourceClass, method); - if (span != null) { - scope = tracer().startScope(span); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - RequestContextHelper.closeSpanAndScope(span, scope, throwable); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyAnnotationInstrumentationTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyAnnotationInstrumentationTest.groovy deleted file mode 100644 index a171d38b7a..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyAnnotationInstrumentationTest.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class JerseyAnnotationInstrumentationTest extends JaxRsAnnotationsInstrumentationTest { -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyFilterTest.groovy deleted file mode 100644 index 11da7ff199..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyFilterTest.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -import io.dropwizard.testing.junit.ResourceTestRule -import javax.ws.rs.client.Entity -import javax.ws.rs.core.Response -import org.junit.ClassRule -import spock.lang.Shared - -class JerseyFilterTest extends JaxRsFilterTest { - @Shared - @ClassRule - ResourceTestRule resources = ResourceTestRule.builder() - .addResource(new Test1()) - .addResource(new Test2()) - .addResource(new Test3()) - .addProvider(simpleRequestFilter) - .addProvider(prematchRequestFilter) - .build() - - @Override - def makeRequest(String url) { - Response response = resources.client().target(url).request().post(Entity.text("")) - - return [response.readEntity(String), response.statusInfo.statusCode] - } -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyHttpServerTest.groovy deleted file mode 100644 index 79898e8cca..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-jersey-2.0/src/test/groovy/JerseyHttpServerTest.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.dropwizard.jetty.NonblockingServletHolder -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.servlet.ServletContextHandler -import org.glassfish.jersey.server.ResourceConfig -import org.glassfish.jersey.servlet.ServletContainer - -class JerseyHttpServerTest extends JaxRsHttpServerTest { - - @Override - Server startServer(int port) { - def servlet = new ServletContainer(ResourceConfig.forApplicationClass(JaxRsTestApplication)) - - def handler = new ServletContextHandler(ServletContextHandler.SESSIONS) - handler.setContextPath("/") - handler.addServlet(new NonblockingServletHolder(servlet), "/*") - - def server = new Server(port) - server.setHandler(handler) - server.start() - - return server - } - - @Override - void stopServer(Server httpServer) { - httpServer.stop() - } -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/jaxrs-2.0-resteasy-3.0.gradle b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/jaxrs-2.0-resteasy-3.0.gradle deleted file mode 100644 index 44c17f8049..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/jaxrs-2.0-resteasy-3.0.gradle +++ /dev/null @@ -1,45 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - // Cant assert fails because muzzle assumes all instrumentations will fail - // Instrumentations in jaxrs-2.0-common will pass - - // Resteasy changes a class's package in 3.1.0 then moves it back in 3.5.0 and then moves it forward again in 4.0.0 - // so the jaxrs-2.0-resteasy-3.0 module applies to [3.0, 3.1) and [3.5, 4.0) - // and the jaxrs-2.0-resteasy-3.1 module applies to [3.1, 3.5) and [4.0, ) - pass { - group = "org.jboss.resteasy" - module = "resteasy-jaxrs" - versions = "[3.0.0.Final,3.1.0.Final)" - } - - pass { - group = "org.jboss.resteasy" - module = "resteasy-jaxrs" - versions = "[3.5.0.Final,4)" - } -} - -dependencies { - compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0' - library group: 'org.jboss.resteasy', name: 'resteasy-jaxrs', version: '3.0.0.Final' - - implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common') - - testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') - testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing') - - testLibrary(group: 'org.jboss.resteasy', name: 'resteasy-undertow', version: '3.0.4.Final') { - exclude group: 'org.jboss.resteasy', module: 'resteasy-client' - } - testLibrary group: 'io.undertow', name: 'undertow-servlet', version: '1.0.0.Final' - - latestDepTestLibrary group: 'org.jboss.resteasy', name: 'resteasy-jaxrs', version: '3.+' - latestDepTestLibrary(group: 'org.jboss.resteasy', name: 'resteasy-undertow', version: '3.+') { - exclude group: 'org.jboss.resteasy', module: 'resteasy-client' - } -} - -test { - systemProperty 'testLatestDeps', testLatestDeps -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy30InstrumentationModule.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy30InstrumentationModule.java deleted file mode 100644 index cff568f3f1..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy30InstrumentationModule.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class Resteasy30InstrumentationModule extends InstrumentationModule { - public Resteasy30InstrumentationModule() { - super("jaxrs", "jaxrs-2.0", "resteasy", "resteasy-3.0"); - } - - @Override - public List typeInstrumentations() { - return Collections.singletonList(new Resteasy30RequestContextInstrumentation()); - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy30RequestContextInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy30RequestContextInstrumentation.java deleted file mode 100644 index cfa4f81e4a..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy30RequestContextInstrumentation.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import javax.ws.rs.container.ContainerRequestContext; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.asm.Advice.Local; -import org.jboss.resteasy.core.ResourceMethodInvoker; -import org.jboss.resteasy.core.interception.PostMatchContainerRequestContext; - -/** - * RESTEasy specific context instrumentation. - * - *

JAX-RS does not define a way to get the matched resource method from the - * ContainerRequestContext - * - *

In the RESTEasy implementation, ContainerRequestContext is implemented by - * PostMatchContainerRequestContext. This class provides a way to get the matched resource - * method through getResourceMethod(). - */ -public class Resteasy30RequestContextInstrumentation extends AbstractRequestContextInstrumentation { - @Override - protected String abortAdviceName() { - return ContainerRequestContextAdvice.class.getName(); - } - - public static class ContainerRequestContextAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void decorateAbortSpan( - @Advice.This ContainerRequestContext context, - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope) { - if (context.getProperty(JaxRsAnnotationsTracer.ABORT_HANDLED) == null - && context instanceof PostMatchContainerRequestContext) { - - ResourceMethodInvoker resourceMethodInvoker = - ((PostMatchContainerRequestContext) context).getResourceMethod(); - Method method = resourceMethodInvoker.getMethod(); - Class resourceClass = resourceMethodInvoker.getResourceClass(); - - span = RequestContextHelper.createOrUpdateAbortSpan(context, resourceClass, method); - if (span != null) { - scope = tracer().startScope(span); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - RequestContextHelper.closeSpanAndScope(span, scope, throwable); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyAnnotationInstrumentationTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyAnnotationInstrumentationTest.groovy deleted file mode 100644 index f86d3473d4..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyAnnotationInstrumentationTest.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class ResteasyAnnotationInstrumentationTest extends JaxRsAnnotationsInstrumentationTest { -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyFilterTest.groovy deleted file mode 100644 index 9b00879b29..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyFilterTest.groovy +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -import javax.ws.rs.core.MediaType -import org.jboss.resteasy.mock.MockDispatcherFactory -import org.jboss.resteasy.mock.MockHttpRequest -import org.jboss.resteasy.mock.MockHttpResponse -import spock.lang.Shared - -class ResteasyFilterTest extends JaxRsFilterTest { - @Shared - def dispatcher - - def setupSpec() { - dispatcher = MockDispatcherFactory.createDispatcher() - def registry = dispatcher.getRegistry() - registry.addSingletonResource(new Test1()) - registry.addSingletonResource(new Test2()) - registry.addSingletonResource(new Test3()) - - dispatcher.getProviderFactory().register(simpleRequestFilter) - dispatcher.getProviderFactory().register(prematchRequestFilter) - } - - @Override - def makeRequest(String url) { - MockHttpRequest request = MockHttpRequest.post(url) - request.contentType(MediaType.TEXT_PLAIN_TYPE) - request.content(new byte[0]) - - MockHttpResponse response = new MockHttpResponse() - dispatcher.invoke(request, response) - - return [response.contentAsString, response.status] - } - -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyHttpServerTest.groovy deleted file mode 100644 index 4967e9dcdd..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.0/src/test/groovy/ResteasyHttpServerTest.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.undertow.Undertow -import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer - -class ResteasyHttpServerTest extends JaxRsHttpServerTest { - - @Override - String getContextPath() { - "/resteasy-context" - } - - @Override - UndertowJaxrsServer startServer(int port) { - def server = new UndertowJaxrsServer() - server.deploy(JaxRsTestApplication, getContextPath()) - server.start(Undertow.builder() - .addHttpListener(port, "localhost")) - return server - } - - @Override - void stopServer(UndertowJaxrsServer server) { - server.stop() - } -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/jaxrs-2.0-resteasy-3.1.gradle b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/jaxrs-2.0-resteasy-3.1.gradle deleted file mode 100644 index 2edc1b1dba..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/jaxrs-2.0-resteasy-3.1.gradle +++ /dev/null @@ -1,49 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - // Cant assert fails because muzzle assumes all instrumentations will fail - // Instrumentations in jaxrs-2.0-common will pass - - // Resteasy changes a class's package in 3.1.0 then moves it back in 3.5.0 and then moves it forward again in 4.0.0 - // so the jaxrs-2.0-resteasy-3.0 module applies to [3.0, 3.1) and [3.5, 4.0) - // and the jaxrs-2.0-resteasy-3.1 module applies to [3.1, 3.5) and [4.0, ) - pass { - group = "org.jboss.resteasy" - module = "resteasy-jaxrs" - versions = "[3.1.0.Final,3.5.0.Final)" - } - - pass { - group = "org.jboss.resteasy" - module = "resteasy-core" - versions = "[4.0.0.Final,)" - } -} - -dependencies { - compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0' - library group: 'org.jboss.resteasy', name: 'resteasy-jaxrs', version: '3.1.0.Final' - - implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common') - - testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') - testImplementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing') - - testLibrary(group: 'org.jboss.resteasy', name: 'resteasy-undertow', version: '3.1.0.Final') { - exclude group: 'org.jboss.resteasy', module: 'resteasy-client' - } - - // artifact name changed from 'resteasy-jaxrs' to 'resteasy-core' starting from version 4.0.0 - latestDepTestLibrary group: 'org.jboss.resteasy', name: 'resteasy-core', version: '+' -} - -test { - systemProperty 'testLatestDeps', testLatestDeps -} - -if (findProperty('testLatestDeps')) { - configurations { - // artifact name changed from 'resteasy-jaxrs' to 'resteasy-core' starting from version 4.0.0 - testImplementation.exclude group: 'org.jboss.resteasy', module: 'resteasy-jaxrs' - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy31InstrumentationModule.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy31InstrumentationModule.java deleted file mode 100644 index 643f208e99..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy31InstrumentationModule.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class Resteasy31InstrumentationModule extends InstrumentationModule { - public Resteasy31InstrumentationModule() { - super("jaxrs", "jaxrs-2.0", "resteasy", "resteasy-3.1"); - } - - @Override - public List typeInstrumentations() { - return Collections.singletonList(new Resteasy31RequestContextInstrumentation()); - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy31RequestContextInstrumentation.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy31RequestContextInstrumentation.java deleted file mode 100644 index af9b63fe8e..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/Resteasy31RequestContextInstrumentation.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.jaxrs.v2_0.JaxRsAnnotationsTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import javax.ws.rs.container.ContainerRequestContext; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.asm.Advice.Local; -import org.jboss.resteasy.core.ResourceMethodInvoker; -import org.jboss.resteasy.core.interception.jaxrs.PostMatchContainerRequestContext; - -/** - * RESTEasy specific context instrumentation. - * - *

JAX-RS does not define a way to get the matched resource method from the - * ContainerRequestContext - * - *

In the RESTEasy implementation, ContainerRequestContext is implemented by - * PostMatchContainerRequestContext. This class provides a way to get the matched resource - * method through getResourceMethod(). - */ -public class Resteasy31RequestContextInstrumentation extends AbstractRequestContextInstrumentation { - @Override - protected String abortAdviceName() { - return ContainerRequestContextAdvice.class.getName(); - } - - public static class ContainerRequestContextAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void decorateAbortSpan( - @Advice.This ContainerRequestContext context, - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope) { - if (context.getProperty(JaxRsAnnotationsTracer.ABORT_HANDLED) == null - && context instanceof PostMatchContainerRequestContext) { - - ResourceMethodInvoker resourceMethodInvoker = - ((PostMatchContainerRequestContext) context).getResourceMethod(); - Method method = resourceMethodInvoker.getMethod(); - Class resourceClass = resourceMethodInvoker.getResourceClass(); - - span = RequestContextHelper.createOrUpdateAbortSpan(context, resourceClass, method); - if (span != null) { - scope = tracer().startScope(span); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Local("otelSpan") Span span, - @Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - RequestContextHelper.closeSpanAndScope(span, scope, throwable); - } - } -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyAnnotationInstrumentationTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyAnnotationInstrumentationTest.groovy deleted file mode 100644 index f86d3473d4..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyAnnotationInstrumentationTest.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class ResteasyAnnotationInstrumentationTest extends JaxRsAnnotationsInstrumentationTest { -} diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyFilterTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyFilterTest.groovy deleted file mode 100644 index 9b00879b29..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyFilterTest.groovy +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Resource.Test1 -import static Resource.Test2 -import static Resource.Test3 - -import javax.ws.rs.core.MediaType -import org.jboss.resteasy.mock.MockDispatcherFactory -import org.jboss.resteasy.mock.MockHttpRequest -import org.jboss.resteasy.mock.MockHttpResponse -import spock.lang.Shared - -class ResteasyFilterTest extends JaxRsFilterTest { - @Shared - def dispatcher - - def setupSpec() { - dispatcher = MockDispatcherFactory.createDispatcher() - def registry = dispatcher.getRegistry() - registry.addSingletonResource(new Test1()) - registry.addSingletonResource(new Test2()) - registry.addSingletonResource(new Test3()) - - dispatcher.getProviderFactory().register(simpleRequestFilter) - dispatcher.getProviderFactory().register(prematchRequestFilter) - } - - @Override - def makeRequest(String url) { - MockHttpRequest request = MockHttpRequest.post(url) - request.contentType(MediaType.TEXT_PLAIN_TYPE) - request.content(new byte[0]) - - MockHttpResponse response = new MockHttpResponse() - dispatcher.invoke(request, response) - - return [response.contentAsString, response.status] - } - -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyHttpServerTest.groovy b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyHttpServerTest.groovy deleted file mode 100644 index 4967e9dcdd..0000000000 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-resteasy-3.1/src/test/groovy/ResteasyHttpServerTest.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.undertow.Undertow -import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer - -class ResteasyHttpServerTest extends JaxRsHttpServerTest { - - @Override - String getContextPath() { - "/resteasy-context" - } - - @Override - UndertowJaxrsServer startServer(int port) { - def server = new UndertowJaxrsServer() - server.deploy(JaxRsTestApplication, getContextPath()) - server.start(Undertow.builder() - .addHttpListener(port, "localhost")) - return server - } - - @Override - void stopServer(UndertowJaxrsServer server) { - server.stop() - } -} \ No newline at end of file diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-testing/jaxrs-2.0-testing.gradle b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-testing/jaxrs-2.0-testing.gradle index fdeca3abc4..9533365df8 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-testing/jaxrs-2.0-testing.gradle +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-testing/jaxrs-2.0-testing.gradle @@ -12,5 +12,5 @@ dependencies { implementation project(':javaagent-api') implementation project(':instrumentation-api') - implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common') + implementation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent') } diff --git a/instrumentation/jdbc/jdbc.gradle b/instrumentation/jdbc/jdbc.gradle deleted file mode 100644 index 303620b12d..0000000000 --- a/instrumentation/jdbc/jdbc.gradle +++ /dev/null @@ -1,24 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk() - } -} - -dependencies { - // jdbc unit testing - testLibrary group: 'com.h2database', name: 'h2', version: '1.3.169' - // first version jdk 1.6 compatible - testLibrary group: 'org.apache.derby', name: 'derby', version: '10.6.1.0' - testLibrary group: 'org.hsqldb', name: 'hsqldb', version: '2.0.0' - - testLibrary group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '7.0.19' - // tomcat needs this to run - testLibrary group: 'org.apache.tomcat', name: 'tomcat-juli', version: '7.0.19' - testLibrary group: 'com.zaxxer', name: 'HikariCP', version: '2.4.0' - testLibrary group: 'com.mchange', name: 'c3p0', version: '0.9.5' - - latestDepTestLibrary group: 'org.apache.derby', name: 'derby', version: '10.14.+' -} - diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java deleted file mode 100644 index 6680025810..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/ConnectionInstrumentation.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.hasInterface; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.sql.PreparedStatement; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class ConnectionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("java.sql.Connection"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("java.sql.Connection")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - nameStartsWith("prepare") - .and(takesArgument(0, String.class)) - // Also include CallableStatement, which is a sub type of PreparedStatement - .and(returns(hasInterface(named("java.sql.PreparedStatement")))), - ConnectionInstrumentation.class.getName() + "$ConnectionPrepareAdvice"); - } - - public static class ConnectionPrepareAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void addDbInfo( - @Advice.Argument(0) String sql, @Advice.Return PreparedStatement statement) { - SqlStatementInfo normalizedSql = JdbcUtils.normalizeAndExtractInfo(sql); - if (normalizedSql != null) { - JdbcMaps.preparedStatements.put(statement, normalizedSql); - } - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DataSourceTracer.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DataSourceTracer.java deleted file mode 100644 index 9c1fbb60bc..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DataSourceTracer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; - -public class DataSourceTracer extends BaseTracer { - private static final DataSourceTracer TRACER = new DataSourceTracer(); - - public static DataSourceTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jdbc"; - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DbInfo.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DbInfo.java deleted file mode 100644 index 708c86ba3a..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DbInfo.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import java.util.Objects; - -public class DbInfo { - - public static final DbInfo DEFAULT = new Builder().build(); - - private final String system; - private final String subtype; - private final String shortUrl; // "type:[subtype:]//host:port" - private final String user; - private final String name; - private final String db; - private final String host; - private final Integer port; - - public DbInfo( - String system, - String subtype, - String shortUrl, - String user, - String name, - String db, - String host, - Integer port) { - this.system = system; - this.subtype = subtype; - this.shortUrl = shortUrl; - this.user = user; - this.name = name; - this.db = db; - this.host = host; - this.port = port; - } - - public String getSystem() { - return system; - } - - public String getSubtype() { - return subtype; - } - - public String getShortUrl() { - return shortUrl; - } - - public String getUser() { - return user; - } - - public String getName() { - return name; - } - - public String getDb() { - return db; - } - - public String getHost() { - return host; - } - - public Integer getPort() { - return port; - } - - public Builder toBuilder() { - return new Builder() - .system(system) - .subtype(subtype) - .shortUrl(shortUrl) - .user(user) - .name(name) - .db(db) - .host(host) - .port(port); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof DbInfo)) { - return false; - } - DbInfo other = (DbInfo) obj; - return Objects.equals(system, other.system) - && Objects.equals(subtype, other.subtype) - && Objects.equals(shortUrl, other.shortUrl) - && Objects.equals(user, other.user) - && Objects.equals(name, other.name) - && Objects.equals(db, other.db) - && Objects.equals(host, other.host) - && Objects.equals(port, other.port); - } - - @Override - public int hashCode() { - return Objects.hash(system, subtype, shortUrl, user, name, db, host, port); - } - - public static class Builder { - private String system; - private String subtype; - private String shortUrl; - private String user; - private String name; - private String db; - private String host; - private Integer port; - - public Builder system(String system) { - this.system = system; - return this; - } - - public Builder subtype(String subtype) { - this.subtype = subtype; - return this; - } - - public Builder shortUrl(String shortUrl) { - this.shortUrl = shortUrl; - return this; - } - - public Builder user(String user) { - this.user = user; - return this; - } - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder db(String db) { - this.db = db; - return this; - } - - public Builder host(String host) { - this.host = host; - return this; - } - - public Builder port(Integer port) { - this.port = port; - return this; - } - - public DbInfo build() { - return new DbInfo(system, subtype, shortUrl, user, name, db, host, port); - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java deleted file mode 100644 index aff2e4ec11..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/DriverInstrumentation.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.sql.Connection; -import java.util.Map; -import java.util.Properties; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class DriverInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("java.sql.Driver"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("java.sql.Driver")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - nameStartsWith("connect") - .and(takesArgument(0, String.class)) - .and(takesArgument(1, Properties.class)) - .and(returns(named("java.sql.Connection"))), - DriverInstrumentation.class.getName() + "$DriverAdvice"); - } - - public static class DriverAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void addDbInfo( - @Advice.Argument(0) String url, - @Advice.Argument(1) Properties props, - @Advice.Return Connection connection) { - if (connection == null) { - // Exception was probably thrown. - return; - } - DbInfo dbInfo = JdbcConnectionUrlParser.parse(url, props); - JdbcMaps.connectionInfo.put(connection, dbInfo); - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcConnectionUrlParser.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcConnectionUrlParser.java deleted file mode 100644 index 01c825c033..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcConnectionUrlParser.java +++ /dev/null @@ -1,965 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.instrumentation.jdbc.DbInfo.DEFAULT; -import static java.util.regex.Pattern.CASE_INSENSITIVE; - -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Structured as an enum instead of a class hierarchy to allow iterating through the parsers - * automatically without having to maintain a separate list of parsers. - */ -public enum JdbcConnectionUrlParser { - GENERIC_URL_LIKE() { - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - try { - // Attempt generic parsing - URI uri = new URI(jdbcUrl); - - populateStandardProperties(builder, splitQuery(uri.getQuery(), "&")); - - String user = uri.getUserInfo(); - if (user != null) { - builder.user(user); - } - - String path = uri.getPath(); - if (path.startsWith("/")) { - path = path.substring(1); - } - if (!path.isEmpty()) { - builder.db(path); - } - - if (uri.getHost() != null) { - builder.host(uri.getHost()); - } - - if (uri.getPort() > 0) { - builder.port(uri.getPort()); - } - - return builder.system(uri.getScheme()); - } catch (Exception e) { - return builder; - } - } - }, - - // see http://jtds.sourceforge.net/faq.html#urlFormat - JTDS_URL_LIKE() { - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - String serverName = ""; - Integer port = null; - - int hostIndex = jdbcUrl.indexOf("jtds:sqlserver://"); - if (hostIndex < 0) { - return builder; - } - - String[] split = jdbcUrl.split(";", 2); - if (split.length > 1) { - Map props = splitQuery(split[1], ";"); - populateStandardProperties(builder, props); - if (props.containsKey("instance")) { - builder.name(props.get("instance")); - } - } - - String urlServerName = split[0].substring(hostIndex + 17); - if (!urlServerName.isEmpty()) { - serverName = urlServerName; - } - - int databaseLoc = serverName.indexOf("/"); - if (databaseLoc > 1) { - builder.db(serverName.substring(databaseLoc + 1)); - serverName = serverName.substring(0, databaseLoc); - } - - int portLoc = serverName.indexOf(":"); - if (portLoc > 1) { - builder.port(Integer.parseInt(serverName.substring(portLoc + 1))); - serverName = serverName.substring(0, portLoc); - } - - if (!serverName.isEmpty()) { - builder.host(serverName); - } - - return builder; - } - }, - - MODIFIED_URL_LIKE() { - // Source: Regular Expressions Cookbook 2nd edition - 8.17. - // Matches Standard, Mixed or Compressed notation in a wider body of text - private final Pattern ipv6 = - Pattern.compile( - // Non Compressed - "(?:(?:(?:[A-F0-9]{1,4}:){6}" - // Compressed with at most 6 colons - + "|(?=(?:[A-F0-9]{0,4}:){0,6}" - // and 4 bytes and anchored - + "(?:[0-9]{1,3}\\.){3}[0-9]{1,3}(?![:.\\w]))" - // and at most 1 double colon - + "(([0-9A-F]{1,4}:){0,5}|:)((:[0-9A-F]{1,4}){1,5}:|:)" - // Compressed with 7 colons and 5 numbers - + "|::(?:[A-F0-9]{1,4}:){5})" - // 255.255.255. - + "(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}" - // 255 - + "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" - // Standard - + "|(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}" - // Compressed with at most 7 colons and anchored - + "|(?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}(?![:.\\w]))" - // and at most 1 double colon - + "(([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:)" - // Compressed with 8 colons - + "|(?:[A-F0-9]{1,4}:){7}:|:(:[A-F0-9]{1,4}){7})(?![:.\\w])", - CASE_INSENSITIVE); - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - String type; - String serverName = ""; - Integer port = null; - String name = null; - - int hostIndex = jdbcUrl.indexOf("://"); - - if (hostIndex <= 0) { - return builder; - } - - type = jdbcUrl.substring(0, hostIndex); - - String[] split; - if (type.equals("db2") || type.equals("as400")) { - if (jdbcUrl.contains("=")) { - int paramLoc = jdbcUrl.lastIndexOf(":"); - split = new String[] {jdbcUrl.substring(0, paramLoc), jdbcUrl.substring(paramLoc + 1)}; - } else { - split = new String[] {jdbcUrl}; - } - } else { - split = jdbcUrl.split(";", 2); - } - - if (split.length > 1) { - Map props = splitQuery(split[1], ";"); - populateStandardProperties(builder, props); - if (props.containsKey("servername")) { - serverName = props.get("servername"); - } - } - - String urlServerName = split[0].substring(hostIndex + 3); - if (!urlServerName.isEmpty()) { - serverName = urlServerName; - } - - int instanceLoc = serverName.indexOf("/"); - if (instanceLoc > 1) { - name = serverName.substring(instanceLoc + 1); - serverName = serverName.substring(0, instanceLoc); - } - - Matcher ipv6Matcher = ipv6.matcher(serverName); - boolean isIpv6 = ipv6Matcher.find(); - - int portLoc = -1; - if (isIpv6) { - if (serverName.startsWith("[")) { - portLoc = serverName.indexOf("]:") + 1; - } else { - serverName = "[" + serverName + "]"; - } - } else { - portLoc = serverName.indexOf(":"); - } - - if (portLoc > 1) { - port = Integer.parseInt(serverName.substring(portLoc + 1)); - serverName = serverName.substring(0, portLoc); - } - - instanceLoc = serverName.indexOf("\\"); - if (instanceLoc > 1) { - if (isIpv6) { - name = serverName.substring(instanceLoc + 1, serverName.lastIndexOf(']')); - serverName = "[" + ipv6Matcher.group(0) + "]"; - } else { - name = serverName.substring(instanceLoc + 1); - serverName = serverName.substring(0, instanceLoc); - } - } - - if (name != null) { - builder.name(name); - } - - if (!serverName.isEmpty()) { - builder.host(serverName); - } - - if (port != null) { - builder.port(port); - } - - return builder; - } - }, - - POSTGRES("postgresql") { - private static final String DEFAULT_HOST = "localhost"; - private static final int DEFAULT_PORT = 5432; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getHost() == null) { - builder.host(DEFAULT_HOST); - } - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - return GENERIC_URL_LIKE.doParse(jdbcUrl, builder); - } - }, - - MYSQL("mysql", "mariadb") { - private static final String DEFAULT_HOST = "localhost"; - private static final int DEFAULT_PORT = 3306; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getHost() == null) { - builder.host(DEFAULT_HOST); - } - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - - int protoLoc = jdbcUrl.indexOf("://"); - int typeEndLoc = jdbcUrl.indexOf(':'); - if (typeEndLoc < protoLoc) { - return MARIA_SUBPROTO - .doParse(jdbcUrl.substring(protoLoc + 3), builder) - .subtype(jdbcUrl.substring(typeEndLoc + 1, protoLoc)); - } - if (protoLoc > 0) { - return GENERIC_URL_LIKE.doParse(jdbcUrl, builder); - } - - int hostEndLoc; - int portLoc = jdbcUrl.indexOf(":", typeEndLoc + 1); - int dbLoc = jdbcUrl.indexOf("/", typeEndLoc); - int paramLoc = jdbcUrl.indexOf("?", dbLoc); - - if (paramLoc > 0) { - populateStandardProperties(builder, splitQuery(jdbcUrl.substring(paramLoc + 1), "&")); - builder.db(jdbcUrl.substring(dbLoc + 1, paramLoc)); - } else { - builder.db(jdbcUrl.substring(dbLoc + 1)); - } - - if (portLoc > 0) { - hostEndLoc = portLoc; - try { - builder.port(Integer.parseInt(jdbcUrl.substring(portLoc + 1, dbLoc))); - } catch (NumberFormatException e) { - log.debug(e.getMessage(), e); - } - } else { - hostEndLoc = dbLoc; - } - - builder.host(jdbcUrl.substring(typeEndLoc + 1, hostEndLoc)); - - return builder; - } - }, - - MARIA_SUBPROTO() { - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - int hostEndLoc; - int clusterSepLoc = jdbcUrl.indexOf(","); - int ipv6End = jdbcUrl.startsWith("[") ? jdbcUrl.indexOf("]") : -1; - int portLoc = jdbcUrl.indexOf(":", Math.max(0, ipv6End)); - portLoc = clusterSepLoc < portLoc ? -1 : portLoc; - int dbLoc = jdbcUrl.indexOf("/", Math.max(portLoc, clusterSepLoc)); - - int paramLoc = jdbcUrl.indexOf("?", dbLoc); - - if (paramLoc > 0) { - populateStandardProperties(builder, splitQuery(jdbcUrl.substring(paramLoc + 1), "&")); - builder.db(jdbcUrl.substring(dbLoc + 1, paramLoc)); - } else { - builder.db(jdbcUrl.substring(dbLoc + 1)); - } - - if (jdbcUrl.startsWith("address=")) { - return MARIA_ADDRESS.doParse(jdbcUrl, builder); - } - - if (portLoc > 0) { - hostEndLoc = portLoc; - int portEndLoc = clusterSepLoc > 0 ? clusterSepLoc : dbLoc; - try { - builder.port(Integer.parseInt(jdbcUrl.substring(portLoc + 1, portEndLoc))); - } catch (NumberFormatException e) { - log.debug(e.getMessage(), e); - } - } else { - hostEndLoc = clusterSepLoc > 0 ? clusterSepLoc : dbLoc; - } - - if (ipv6End > 0) { - builder.host(jdbcUrl.substring(1, ipv6End)); - } else { - builder.host(jdbcUrl.substring(0, hostEndLoc)); - } - return builder; - } - }, - - MARIA_ADDRESS() { - private final Pattern hostPattern = Pattern.compile("\\(\\s*host\\s*=\\s*([^ )]+)\\s*\\)"); - private final Pattern portPattern = Pattern.compile("\\(\\s*port\\s*=\\s*([\\d]+)\\s*\\)"); - private final Pattern userPattern = Pattern.compile("\\(\\s*user\\s*=\\s*([^ )]+)\\s*\\)"); - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - int addressEnd = jdbcUrl.indexOf(",address="); - if (addressEnd > 0) { - jdbcUrl = jdbcUrl.substring(0, addressEnd); - } - Matcher hostMatcher = hostPattern.matcher(jdbcUrl); - if (hostMatcher.find()) { - builder.host(hostMatcher.group(1)); - } - - Matcher portMatcher = portPattern.matcher(jdbcUrl); - if (portMatcher.find()) { - builder.port(Integer.parseInt(portMatcher.group(1))); - } - - Matcher userMatcher = userPattern.matcher(jdbcUrl); - if (userMatcher.find()) { - builder.user(userMatcher.group(1)); - } - - return builder; - } - }, - - SAP("sap") { - private static final String DEFAULT_HOST = "localhost"; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getHost() == null) { - builder.host(DEFAULT_HOST); - } - return GENERIC_URL_LIKE.doParse(jdbcUrl, builder); - } - }, - - MSSQLSERVER("jtds", "microsoft", "sqlserver") { - private static final String DEFAULT_HOST = "localhost"; - private static final int DEFAULT_PORT = 1433; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getHost() == null) { - builder.host(DEFAULT_HOST); - } - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - - int protoLoc = jdbcUrl.indexOf("://"); - int typeEndLoc = jdbcUrl.indexOf(':'); - if (protoLoc > typeEndLoc) { - String subtype = jdbcUrl.substring(typeEndLoc + 1, protoLoc); - builder.subtype(subtype); - } - - if (jdbcUrl.startsWith("jtds:")) { - return JTDS_URL_LIKE.doParse(jdbcUrl, builder); - } - - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder); - } - }, - - DB2("db2", "as400") { - private static final int DEFAULT_PORT = 50000; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder); - } - }, - - ORACLE("oracle") { - private static final int DEFAULT_PORT = 1521; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - int typeEndIndex = jdbcUrl.indexOf(":", "oracle:".length()); - String subtype = jdbcUrl.substring("oracle:".length(), typeEndIndex); - jdbcUrl = jdbcUrl.substring(typeEndIndex + 1); - - builder.subtype(subtype); - DbInfo dbInfo = builder.build(); - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - - if (jdbcUrl.contains("@")) { - return ORACLE_AT.doParse(jdbcUrl, builder); - } else { - return ORACLE_CONNECT_INFO.doParse(jdbcUrl, builder); - } - } - }, - - ORACLE_CONNECT_INFO() { - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - - String host; - Integer port; - String instance; - - int hostEnd = jdbcUrl.indexOf(":"); - int instanceLoc = jdbcUrl.indexOf("/"); - if (hostEnd > 0) { - host = jdbcUrl.substring(0, hostEnd); - int afterHostEnd = jdbcUrl.indexOf(":", hostEnd + 1); - if (afterHostEnd > 0) { - port = Integer.parseInt(jdbcUrl.substring(hostEnd + 1, afterHostEnd)); - instance = jdbcUrl.substring(afterHostEnd + 1); - } else { - if (instanceLoc > 0) { - instance = jdbcUrl.substring(instanceLoc + 1); - port = Integer.parseInt(jdbcUrl.substring(hostEnd + 1, instanceLoc)); - } else { - String portOrInstance = jdbcUrl.substring(hostEnd + 1); - Integer parsedPort = null; - try { - parsedPort = Integer.parseInt(portOrInstance); - } catch (NumberFormatException e) { - log.debug(e.getMessage(), e); - } - if (parsedPort == null) { - port = null; - instance = portOrInstance; - } else { - port = parsedPort; - instance = null; - } - } - } - } else { - if (instanceLoc > 0) { - host = jdbcUrl.substring(0, instanceLoc); - port = null; - instance = jdbcUrl.substring(instanceLoc + 1); - } else { - if (jdbcUrl.isEmpty()) { - return builder; - } else { - host = null; - port = null; - instance = jdbcUrl; - } - } - } - if (host != null) { - builder.host(host); - } - if (port != null) { - builder.port(port); - } - return builder.name(instance); - } - }, - - ORACLE_AT() { - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - if (jdbcUrl.contains("@(description")) { - return ORACLE_AT_DESCRIPTION.doParse(jdbcUrl, builder); - } - String user; - - String[] atSplit = jdbcUrl.split("@", 2); - - int userInfoLoc = atSplit[0].indexOf("/"); - if (userInfoLoc > 0) { - user = atSplit[0].substring(0, userInfoLoc); - } else { - user = null; - } - - String connectInfo = atSplit[1]; - int hostStart; - if (connectInfo.startsWith("//")) { - hostStart = "//".length(); - } else if (connectInfo.startsWith("ldap://")) { - hostStart = "ldap://".length(); - } else { - hostStart = 0; - } - if (user != null) { - builder.user(user); - } - return ORACLE_CONNECT_INFO.doParse(connectInfo.substring(hostStart), builder); - } - }, - - /** - * This parser can locate incorrect data if multiple addresses are defined but not everything is - * defined in the first block. (It would locate data from subsequent address blocks. - */ - ORACLE_AT_DESCRIPTION() { - private final Pattern hostPattern = Pattern.compile("\\(\\s*host\\s*=\\s*([^ )]+)\\s*\\)"); - private final Pattern portPattern = Pattern.compile("\\(\\s*port\\s*=\\s*([\\d]+)\\s*\\)"); - private final Pattern instancePattern = - Pattern.compile("\\(\\s*service_name\\s*=\\s*([^ )]+)\\s*\\)"); - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - String[] atSplit = jdbcUrl.split("@", 2); - - int userInfoLoc = atSplit[0].indexOf("/"); - if (userInfoLoc > 0) { - builder.user(atSplit[0].substring(0, userInfoLoc)); - } - - Matcher hostMatcher = hostPattern.matcher(atSplit[1]); - if (hostMatcher.find()) { - builder.host(hostMatcher.group(1)); - } - - Matcher portMatcher = portPattern.matcher(atSplit[1]); - if (portMatcher.find()) { - builder.port(Integer.parseInt(portMatcher.group(1))); - } - - Matcher instanceMatcher = instancePattern.matcher(atSplit[1]); - if (instanceMatcher.find()) { - builder.name(instanceMatcher.group(1)); - } - - return builder; - } - }, - - H2("h2") { - private static final int DEFAULT_PORT = 8082; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - String instance; - - String h2Url = jdbcUrl.substring("h2:".length()); - if (h2Url.startsWith("mem:")) { - builder.subtype("mem").host(null).port(null); - int propLoc = h2Url.indexOf(";"); - if (propLoc >= 0) { - instance = h2Url.substring("mem:".length(), propLoc); - } else { - instance = h2Url.substring("mem:".length()); - } - } else if (h2Url.startsWith("file:")) { - builder.subtype("file").host(null).port(null); - int propLoc = h2Url.indexOf(";"); - if (propLoc >= 0) { - instance = h2Url.substring("file:".length(), propLoc); - } else { - instance = h2Url.substring("file:".length()); - } - } else if (h2Url.startsWith("zip:")) { - builder.subtype("zip").host(null).port(null); - int propLoc = h2Url.indexOf(";"); - if (propLoc >= 0) { - instance = h2Url.substring("zip:".length(), propLoc); - } else { - instance = h2Url.substring("zip:".length()); - } - } else if (h2Url.startsWith("tcp:")) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder).system(DbSystem.H2).subtype("tcp"); - } else if (h2Url.startsWith("ssl:")) { - DbInfo dbInfo = builder.build(); - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder).system(DbSystem.H2).subtype("ssl"); - } else { - builder.subtype("file").host(null).port(null); - int propLoc = h2Url.indexOf(";"); - if (propLoc >= 0) { - instance = h2Url.substring(0, propLoc); - } else { - instance = h2Url; - } - } - if (!instance.isEmpty()) { - builder.name(instance); - } - return builder; - } - }, - - HSQL("hsqldb") { - private static final String DEFAULT_USER = "SA"; - private static final int DEFAULT_PORT = 9001; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - String instance = null; - DbInfo dbInfo = builder.build(); - if (dbInfo.getUser() == null) { - builder.user(DEFAULT_USER); - } - String hsqlUrl = jdbcUrl.substring("hsqldb:".length()); - int proIndex = hsqlUrl.indexOf(";"); - if (proIndex >= 0) { - hsqlUrl = hsqlUrl.substring(0, proIndex); - } else { - int varIndex = hsqlUrl.indexOf("?"); - if (varIndex >= 0) { - hsqlUrl = hsqlUrl.substring(0, varIndex); - } - } - if (hsqlUrl.startsWith("mem:")) { - builder.subtype("mem").host(null).port(null); - instance = hsqlUrl.substring("mem:".length()); - } else if (hsqlUrl.startsWith("file:")) { - builder.subtype("file").host(null).port(null); - instance = hsqlUrl.substring("file:".length()); - } else if (hsqlUrl.startsWith("res:")) { - builder.subtype("res").host(null).port(null); - instance = hsqlUrl.substring("res:".length()); - } else if (hsqlUrl.startsWith("hsql:")) { - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder).system(DbSystem.HSQLDB).subtype("hsql"); - } else if (hsqlUrl.startsWith("hsqls:")) { - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder).system(DbSystem.HSQLDB).subtype("hsqls"); - } else if (hsqlUrl.startsWith("http:")) { - if (dbInfo.getPort() == null) { - builder.port(80); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder).system(DbSystem.HSQLDB).subtype("http"); - } else if (hsqlUrl.startsWith("https:")) { - if (dbInfo.getPort() == null) { - builder.port(443); - } - return MODIFIED_URL_LIKE.doParse(jdbcUrl, builder).system(DbSystem.HSQLDB).subtype("https"); - } else { - builder.subtype("mem").host(null).port(null); - instance = hsqlUrl; - } - return builder.name(instance); - } - }, - - DERBY("derby") { - private static final String DEFAULT_USER = "APP"; - private static final int DEFAULT_PORT = 1527; - - @Override - DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder) { - String instance = null; - String host = null; - - DbInfo dbInfo = builder.build(); - if (dbInfo.getUser() == null) { - builder.user(DEFAULT_USER); - } - - String derbyUrl = jdbcUrl.substring("derby:".length()); - String[] split = derbyUrl.split(";", 2); - - if (split.length > 1) { - populateStandardProperties(builder, splitQuery(split[1], ";")); - } - - String details = split[0]; - if (details.startsWith("memory:")) { - builder.subtype("memory").host(null).port(null); - String urlInstance = details.substring("memory:".length()); - if (!urlInstance.isEmpty()) { - instance = urlInstance; - } - } else if (details.startsWith("directory:")) { - builder.subtype("directory").host(null).port(null); - String urlInstance = details.substring("directory:".length()); - if (!urlInstance.isEmpty()) { - instance = urlInstance; - } - } else if (details.startsWith("classpath:")) { - builder.subtype("classpath").host(null).port(null); - String urlInstance = details.substring("classpath:".length()); - if (!urlInstance.isEmpty()) { - instance = urlInstance; - } - } else if (details.startsWith("jar:")) { - builder.subtype("jar").host(null).port(null); - String urlInstance = details.substring("jar:".length()); - if (!urlInstance.isEmpty()) { - instance = urlInstance; - } - } else if (details.startsWith("//")) { - builder.subtype("network"); - if (dbInfo.getPort() == null) { - builder.port(DEFAULT_PORT); - } - String url = details.substring("//".length()); - int instanceLoc = url.indexOf("/"); - if (instanceLoc >= 0) { - instance = url.substring(instanceLoc + 1); - int protoLoc = instance.indexOf(":"); - if (protoLoc >= 0) { - instance = instance.substring(protoLoc + 1); - } - url = url.substring(0, instanceLoc); - } - int portLoc = url.indexOf(":"); - if (portLoc > 0) { - host = url.substring(0, portLoc); - builder.port(Integer.parseInt(url.substring(portLoc + 1))); - } else { - host = url; - } - } else { - builder.subtype("directory").host(null).port(null); - String urlInstance = details; - if (!urlInstance.isEmpty()) { - instance = urlInstance; - } - } - - if (host != null) { - builder.host(host); - } - return builder.name(instance); - } - }; - - private static final Logger log = LoggerFactory.getLogger(JdbcConnectionUrlParser.class); - - private static final Map typeParsers = new HashMap<>(); - - static { - for (JdbcConnectionUrlParser parser : JdbcConnectionUrlParser.values()) { - for (String key : parser.typeKeys) { - typeParsers.put(key, parser); - } - } - } - - private final String[] typeKeys; - - JdbcConnectionUrlParser(String... typeKeys) { - this.typeKeys = typeKeys; - } - - abstract DbInfo.Builder doParse(String jdbcUrl, DbInfo.Builder builder); - - public static DbInfo parse(String connectionUrl, Properties props) { - if (connectionUrl == null) { - return DEFAULT; - } - // Make this easier and ignore case. - connectionUrl = connectionUrl.toLowerCase(); - - if (!connectionUrl.startsWith("jdbc:")) { - return DEFAULT; - } - - String jdbcUrl = connectionUrl.substring("jdbc:".length()); - int typeLoc = jdbcUrl.indexOf(':'); - - if (typeLoc < 1) { - // Invalid format: `jdbc:` or `jdbc::` - return DEFAULT; - } - - String type = jdbcUrl.substring(0, typeLoc); - String system = toDbSystem(type); - DbInfo.Builder parsedProps = DEFAULT.toBuilder().system(system); - populateStandardProperties(parsedProps, props); - - try { - if (typeParsers.containsKey(type)) { - // Delegate to specific parser - return withUrl(typeParsers.get(type).doParse(jdbcUrl, parsedProps), type); - } - return withUrl(GENERIC_URL_LIKE.doParse(jdbcUrl, parsedProps), type); - } catch (Exception e) { - log.debug("Error parsing URL", e); - return parsedProps.build(); - } - } - - private static DbInfo withUrl(DbInfo.Builder builder, String type) { - DbInfo info = builder.build(); - StringBuilder url = new StringBuilder(); - url.append(type); - url.append(':'); - String subtype = info.getSubtype(); - if (subtype != null) { - url.append(subtype); - url.append(':'); - } - String host = info.getHost(); - if (host != null) { - url.append("//"); - url.append(host); - Integer port = info.getPort(); - if (port != null) { - url.append(':'); - url.append(port); - } - } - return builder.shortUrl(url.toString()).build(); - } - - // Source: https://stackoverflow.com/a/13592567 - private static Map splitQuery(String query, String separator) { - if (query == null || query.isEmpty()) { - return Collections.emptyMap(); - } - Map queryPairs = new LinkedHashMap<>(); - String[] pairs = query.split(separator); - for (String pair : pairs) { - try { - int idx = pair.indexOf("="); - String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair; - if (!queryPairs.containsKey(key)) { - String value = - idx > 0 && pair.length() > idx + 1 - ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") - : null; - queryPairs.put(key, value); - } - } catch (UnsupportedEncodingException e) { - // Ignore. - } - } - return queryPairs; - } - - private static void populateStandardProperties( - DbInfo.Builder builder, Map props) { - if (props != null && !props.isEmpty()) { - if (props.containsKey("user")) { - builder.user((String) props.get("user")); - } - - if (props.containsKey("databasename")) { - builder.db((String) props.get("databasename")); - } - if (props.containsKey("databaseName")) { - builder.db((String) props.get("databaseName")); - } - - if (props.containsKey("servername")) { - builder.host((String) props.get("servername")); - } - if (props.containsKey("serverName")) { - builder.host((String) props.get("serverName")); - } - - if (props.containsKey("portnumber")) { - String portNumber = (String) props.get("portnumber"); - try { - builder.port(Integer.parseInt(portNumber)); - } catch (NumberFormatException e) { - log.debug("Error parsing portnumber property: " + portNumber, e); - } - } - - if (props.containsKey("portNumber")) { - String portNumber = (String) props.get("portNumber"); - try { - builder.port(Integer.parseInt(portNumber)); - } catch (NumberFormatException e) { - log.debug("Error parsing portNumber property: " + portNumber, e); - } - } - } - } - - // see - // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md - private static String toDbSystem(String type) { - switch (type) { - case "as400": // IBM AS400 Database - case "db2": // IBM Db2 - return DbSystem.DB2; - case "derby": // Apache Derby - return DbSystem.DERBY; - case "h2": // H2 Database - return DbSystem.H2; - case "hsqldb": // Hyper SQL Database - return DbSystem.HSQLDB; - case "mariadb": // MariaDB - return DbSystem.MARIADB; - case "mysql": // MySQL - return DbSystem.MYSQL; - case "oracle": // Oracle Database - return DbSystem.ORACLE; - case "postgresql": // PostgreSQL - return DbSystem.POSTGRESQL; - case "jtds": // jTDS - the pure Java JDBC 3.0 driver for Microsoft SQL Server - case "microsoft": - case "sqlserver": // Microsoft SQL Server - return DbSystem.MSSQL; - default: - return DbSystem.OTHER_SQL; // Unknown DBMS - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcDataSourceInstrumentationModule.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcDataSourceInstrumentationModule.java deleted file mode 100644 index 384ee7d27f..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcDataSourceInstrumentationModule.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT; -import static io.opentelemetry.javaagent.instrumentation.jdbc.DataSourceTracer.tracer; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import javax.sql.DataSource; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class JdbcDataSourceInstrumentationModule extends InstrumentationModule { - public JdbcDataSourceInstrumentationModule() { - super("jdbc-datasource"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new DataSourceInstrumentation()); - } - - @Override - public boolean defaultEnabled() { - return false; - } - - public static class DataSourceInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.sql.DataSource")); - } - - @Override - public Map, String> transformers() { - return singletonMap(named("getConnection"), GetConnectionAdvice.class.getName()); - } - } - - public static class GetConnectionAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void start( - @Advice.This DataSource ds, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - // TODO this is very strange condition - if (!Java8BytecodeBridge.currentSpan().getSpanContext().isValid()) { - // Don't want to generate a new top-level span - return; - } - - span = tracer().startSpan(ds.getClass().getSimpleName() + ".getConnection", CLIENT); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - if (scope == null) { - return; - } - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcInstrumentationModule.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcInstrumentationModule.java deleted file mode 100644 index b95d5237f3..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcInstrumentationModule.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class JdbcInstrumentationModule extends InstrumentationModule { - public JdbcInstrumentationModule() { - super("jdbc"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ConnectionInstrumentation(), - new DriverInstrumentation(), - new PreparedStatementInstrumentation(), - new StatementInstrumentation()); - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java deleted file mode 100644 index 7d55428931..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcMaps.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.instrumentation.api.WeakMap.Provider.newWeakMap; - -import io.opentelemetry.javaagent.instrumentation.api.WeakMap; -import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; -import java.sql.Connection; -import java.sql.PreparedStatement; - -/** - * JDBC instrumentation shares a global map of connection info. - * - *

Should be injected into the bootstrap classpath. - */ -public class JdbcMaps { - public static final WeakMap connectionInfo = newWeakMap(); - public static final WeakMap preparedStatements = - newWeakMap(); -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java deleted file mode 100644 index 12710fe425..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcTracer.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.instrumentation.jdbc.JdbcUtils.connectionFromStatement; -import static io.opentelemetry.javaagent.instrumentation.jdbc.JdbcUtils.normalizeAndExtractInfo; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; -import java.net.InetSocketAddress; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; - -public class JdbcTracer extends DatabaseClientTracer { - private static final JdbcTracer TRACER = new JdbcTracer(); - - public static JdbcTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jdbc"; - } - - @Override - protected String dbSystem(DbInfo info) { - return info.getSystem(); - } - - @Override - protected String dbUser(DbInfo info) { - return info.getUser(); - } - - @Override - protected String dbName(DbInfo info) { - if (info.getName() != null) { - return info.getName(); - } else { - return info.getDb(); - } - } - - // TODO find a way to implement - @Override - protected InetSocketAddress peerAddress(DbInfo dbInfo) { - return null; - } - - @Override - protected String dbConnectionString(DbInfo info) { - return info.getShortUrl(); - } - - public Depth getCallDepth() { - return CallDepthThreadLocalMap.getCallDepth(Statement.class); - } - - public Span startSpan(PreparedStatement statement) { - return startSpan(statement, JdbcMaps.preparedStatements.get(statement)); - } - - public Span startSpan(Statement statement, String query) { - return startSpan(statement, normalizeAndExtractInfo(query)); - } - - public Span startSpan(Statement statement, SqlStatementInfo queryInfo) { - Connection connection = connectionFromStatement(statement); - if (connection == null) { - return null; - } - - DbInfo dbInfo = extractDbInfo(connection); - - return startSpan(dbInfo, queryInfo); - } - - @Override - protected String normalizeQuery(SqlStatementInfo query) { - return query.getFullStatement(); - } - - @Override - protected String spanName(DbInfo connection, SqlStatementInfo query, String normalizedQuery) { - String dbName = dbName(connection); - if (query.getOperation() == null) { - return dbName == null ? DB_QUERY : dbName; - } - - StringBuilder name = new StringBuilder(); - name.append(query.getOperation()).append(' '); - if (dbName != null) { - name.append(dbName); - if (query.getTable() != null) { - name.append('.'); - } - } - if (query.getTable() != null) { - name.append(query.getTable()); - } - return name.toString(); - } - - private DbInfo extractDbInfo(Connection connection) { - DbInfo dbInfo = JdbcMaps.connectionInfo.get(connection); - /* - * Logic to get the DBInfo from a JDBC Connection, if the connection was not created via - * Driver.connect, or it has never seen before, the connectionInfo map will return null and will - * attempt to extract DBInfo from the connection. If the DBInfo can't be extracted, then the - * connection will be stored with the DEFAULT DBInfo as the value in the connectionInfo map to - * avoid retry overhead. - */ - { - if (dbInfo == null) { - try { - DatabaseMetaData metaData = connection.getMetaData(); - String url = metaData.getURL(); - if (url != null) { - try { - dbInfo = JdbcConnectionUrlParser.parse(url, connection.getClientInfo()); - } catch (Throwable ex) { - // getClientInfo is likely not allowed. - dbInfo = JdbcConnectionUrlParser.parse(url, null); - } - } else { - dbInfo = DbInfo.DEFAULT; - } - } catch (SQLException se) { - dbInfo = DbInfo.DEFAULT; - } - JdbcMaps.connectionInfo.put(connection, dbInfo); - } - } - return dbInfo; - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcUtils.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcUtils.java deleted file mode 100644 index 8d68a68bd3..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcUtils.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.instrumentation.api.db.QueryNormalizationConfig.isQueryNormalizationEnabled; - -import io.opentelemetry.javaagent.instrumentation.api.db.SqlStatementInfo; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.ParseException; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlNormalizer; -import io.opentelemetry.javaagent.instrumentation.api.db.normalizer.SqlStatementInfoExtractor; -import java.lang.reflect.Field; -import java.sql.Connection; -import java.sql.Statement; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class JdbcUtils { - - private static final Logger log = LoggerFactory.getLogger(JdbcUtils.class); - - private static final boolean NORMALIZATION_ENABLED = isQueryNormalizationEnabled("jdbc"); - - private static Field c3poField = null; - - /** Returns the unwrapped connection or null if exception was thrown. */ - public static Connection connectionFromStatement(Statement statement) { - Connection connection; - try { - connection = statement.getConnection(); - - if (c3poField != null) { - if (connection.getClass().getName().equals("com.mchange.v2.c3p0.impl.NewProxyConnection")) { - return (Connection) c3poField.get(connection); - } - } - - try { - // unwrap the connection to cache the underlying actual connection and to not cache proxy - // objects - if (connection.isWrapperFor(Connection.class)) { - connection = connection.unwrap(Connection.class); - } - } catch (Exception | AbstractMethodError e) { - if (connection != null) { - // Attempt to work around c3po delegating to an connection that doesn't support - // unwrapping. - Class connectionClass = connection.getClass(); - if (connectionClass.getName().equals("com.mchange.v2.c3p0.impl.NewProxyConnection")) { - Field inner = connectionClass.getDeclaredField("inner"); - inner.setAccessible(true); - c3poField = inner; - return (Connection) c3poField.get(connection); - } - } - - // perhaps wrapping isn't supported? - // ex: org.h2.jdbc.JdbcConnection v1.3.175 - // or: jdts.jdbc which always throws `AbstractMethodError` (at least up to version 1.3) - // Stick with original connection. - } - } catch (Throwable e) { - // Had some problem getting the connection. - log.debug("Could not get connection for StatementAdvice", e); - return null; - } - return connection; - } - - /** Returns null if the sql could not be normalized for any reason. */ - public static String normalizeSql(String sql) { - if (!NORMALIZATION_ENABLED) { - return sql; - } - try { - return SqlNormalizer.normalize(sql); - } catch (Exception e) { - log.debug("Could not normalize sql", e); - return null; - } - } - - public static SqlStatementInfo normalizeAndExtractInfo(String sql) { - try { - return SqlStatementInfoExtractor.extract(normalizeSql(sql)); - } catch (ParseException e) { - log.debug("Could not extract sql info", e); - return new SqlStatementInfo(null, null, null); - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java deleted file mode 100644 index 39f112f4c8..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.instrumentation.jdbc.JdbcTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.sql.PreparedStatement; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class PreparedStatementInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("java.sql.PreparedStatement"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("java.sql.PreparedStatement")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - nameStartsWith("execute").and(takesArguments(0)).and(isPublic()), - PreparedStatementInstrumentation.class.getName() + "$PreparedStatementAdvice"); - } - - public static class PreparedStatementAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This PreparedStatement statement, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(statement); - if (span != null) { - scope = tracer().startScope(span); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - } - } - } -} diff --git a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/StatementInstrumentation.java b/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/StatementInstrumentation.java deleted file mode 100644 index 45b630edf9..0000000000 --- a/instrumentation/jdbc/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/StatementInstrumentation.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jdbc; - -import static io.opentelemetry.javaagent.instrumentation.jdbc.JdbcTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.sql.Statement; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class StatementInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("java.sql.Statement"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("java.sql.Statement")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - nameStartsWith("execute").and(takesArgument(0, String.class)).and(isPublic()), - StatementInstrumentation.class.getName() + "$StatementAdvice"); - } - - public static class StatementAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) String sql, - @Advice.This Statement statement, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(statement, sql); - if (span != null) { - scope = tracer().startScope(span); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - } - } - } -} diff --git a/instrumentation/jdbc/src/test/groovy/JdbcConnectionUrlParserTest.groovy b/instrumentation/jdbc/src/test/groovy/JdbcConnectionUrlParserTest.groovy deleted file mode 100644 index 6c89df9be2..0000000000 --- a/instrumentation/jdbc/src/test/groovy/JdbcConnectionUrlParserTest.groovy +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.javaagent.instrumentation.jdbc.JdbcConnectionUrlParser.parse - -import io.opentelemetry.javaagent.instrumentation.jdbc.DbInfo -import spock.lang.Shared -import spock.lang.Specification - -class JdbcConnectionUrlParserTest extends Specification { - - @Shared - def stdProps = { - def prop = new Properties() - // https://download.oracle.com/otn-pub/jcp/jdbc-4_1-mrel-spec/jdbc4.1-fr-spec.pdf - prop.setProperty("databaseName", "stdDatabaseName") - prop.setProperty("dataSourceName", "stdDatasourceName") - prop.setProperty("description", "Some description") - prop.setProperty("networkProtocol", "stdProto") - prop.setProperty("password", "PASSWORD!") - prop.setProperty("portNumber", "9999") - prop.setProperty("roleName", "stdRoleName") - prop.setProperty("serverName", "stdServerName") - prop.setProperty("user", "stdUserName") - return prop - }() - - def "invalid url returns default"() { - expect: - parse(url, null) == DbInfo.DEFAULT - - where: - url | _ - null | _ - "" | _ - "jdbc:" | _ - "jdbc::" | _ - "bogus:string" | _ - } - - def "verify #system:#subtype parsing of #url"() { - setup: - def info = parse(url, props) - - expect: - info.shortUrl == expected.shortUrl - info.system == expected.system - info.host == expected.host - info.port == expected.port - info.user == expected.user - info.name == expected.name - - info == expected - - where: - url | props | shortUrl | system | subtype | user | host | port | name | db - // https://jdbc.postgresql.org/documentation/94/connect.html - "jdbc:postgresql:///" | null | "postgresql://localhost:5432" | "postgresql" | null | null | "localhost" | 5432 | null | null - "jdbc:postgresql:///" | stdProps | "postgresql://stdServerName:9999" | "postgresql" | null | "stdUserName" | "stdServerName" | 9999 | null | "stdDatabaseName" - "jdbc:postgresql://pg.host" | null | "postgresql://pg.host:5432" | "postgresql" | null | null | "pg.host" | 5432 | null | null - "jdbc:postgresql://pg.host:11/pgdb?user=pguser&password=PW" | null | "postgresql://pg.host:11" | "postgresql" | null | "pguser" | "pg.host" | 11 | null | "pgdb" - - "jdbc:postgresql://pg.host:11/pgdb?user=pguser&password=PW" | stdProps | "postgresql://pg.host:11" | "postgresql" | null | "pguser" | "pg.host" | 11 | null | "pgdb" - - // https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-jdbc-url-format.html - // https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html - "jdbc:mysql:///" | null | "mysql://localhost:3306" | "mysql" | null | null | "localhost" | 3306 | null | null - "jdbc:mysql:///" | stdProps | "mysql://stdServerName:9999" | "mysql" | null | "stdUserName" | "stdServerName" | 9999 | null | "stdDatabaseName" - "jdbc:mysql://my.host" | null | "mysql://my.host:3306" | "mysql" | null | null | "my.host" | 3306 | null | null - "jdbc:mysql://my.host?user=myuser&password=PW" | null | "mysql://my.host:3306" | "mysql" | null | "myuser" | "my.host" | 3306 | null | null - "jdbc:mysql://my.host:22/mydb?user=myuser&password=PW" | null | "mysql://my.host:22" | "mysql" | null | "myuser" | "my.host" | 22 | null | "mydb" - "jdbc:mysql://127.0.0.1:22/mydb?user=myuser&password=PW" | stdProps | "mysql://127.0.0.1:22" | "mysql" | null | "myuser" | "127.0.0.1" | 22 | null | "mydb" - - // https://mariadb.com/kb/en/library/about-mariadb-connector-j/#connection-strings - "jdbc:mariadb:127.0.0.1:33/mdbdb" | null | "mariadb://127.0.0.1:33" | "mariadb" | null | null | "127.0.0.1" | 33 | null | "mdbdb" - "jdbc:mariadb:localhost/mdbdb" | null | "mariadb://localhost:3306" | "mariadb" | null | null | "localhost" | 3306 | null | "mdbdb" - "jdbc:mariadb:localhost/mdbdb?user=mdbuser&password=PW" | stdProps | "mariadb://localhost:9999" | "mariadb" | null | "mdbuser" | "localhost" | 9999 | null | "mdbdb" - "jdbc:mariadb:localhost:33/mdbdb" | stdProps | "mariadb://localhost:33" | "mariadb" | null | "stdUserName" | "localhost" | 33 | null | "mdbdb" - "jdbc:mariadb://mdb.host:33/mdbdb?user=mdbuser&password=PW" | null | "mariadb://mdb.host:33" | "mariadb" | null | "mdbuser" | "mdb.host" | 33 | null | "mdbdb" - "jdbc:mariadb:aurora://mdb.host/mdbdb" | null | "mariadb:aurora://mdb.host:3306" | "mariadb" | "aurora" | null | "mdb.host" | 3306 | null | "mdbdb" - "jdbc:mysql:aurora://mdb.host/mdbdb" | null | "mysql:aurora://mdb.host:3306" | "mysql" | "aurora" | null | "mdb.host" | 3306 | null | "mdbdb" - "jdbc:mysql:failover://localhost/mdbdb?autoReconnect=true" | null | "mysql:failover://localhost:3306" | "mysql" | "failover" | null | "localhost" | 3306 | null | "mdbdb" - "jdbc:mariadb:failover://mdb.host1:33,mdb.host/mdbdb?characterEncoding=utf8" | null | "mariadb:failover://mdb.host1:33" | "mariadb" | "failover" | null | "mdb.host1" | 33 | null | "mdbdb" - "jdbc:mariadb:sequential://mdb.host1,mdb.host2:33/mdbdb" | null | "mariadb:sequential://mdb.host1:3306" | "mariadb" | "sequential" | null | "mdb.host1" | 3306 | null | "mdbdb" - "jdbc:mariadb:loadbalance://127.0.0.1:33,mdb.host/mdbdb" | null | "mariadb:loadbalance://127.0.0.1:33" | "mariadb" | "loadbalance" | null | "127.0.0.1" | 33 | null | "mdbdb" - "jdbc:mariadb:loadbalance://[2001:0660:7401:0200:0000:0000:0edf:bdd7]:33,mdb.host/mdbdb" | null | "mariadb:loadbalance://2001:0660:7401:0200:0000:0000:0edf:bdd7:33" | "mariadb" | "loadbalance" | null | "2001:0660:7401:0200:0000:0000:0edf:bdd7" | 33 | null | "mdbdb" - "jdbc:mysql:loadbalance://127.0.0.1,127.0.0.1:3306/mdbdb?user=mdbuser&password=PW" | null | "mysql:loadbalance://127.0.0.1:3306" | "mysql" | "loadbalance" | "mdbuser" | "127.0.0.1" | 3306 | null | "mdbdb" - "jdbc:mariadb:replication://localhost:33,anotherhost:3306/mdbdb" | null | "mariadb:replication://localhost:33" | "mariadb" | "replication" | null | "localhost" | 33 | null | "mdbdb" - "jdbc:mysql:replication://address=(HOST=127.0.0.1)(port=33)(user=mdbuser)(password=PW)," + - "address=(host=mdb.host)(port=3306)(user=otheruser)(password=PW)/mdbdb?user=wrong&password=PW" | null | "mysql:replication://127.0.0.1:33" | "mysql" | "replication" | "mdbuser" | "127.0.0.1" | 33 | null | "mdbdb" - "jdbc:mysql:replication://address=(HOST=mdb.host)," + - "address=(host=anotherhost)(port=3306)(user=wrong)(password=PW)/mdbdb?user=mdbuser&password=PW" | null | "mysql:replication://mdb.host:3306" | "mysql" | "replication" | "mdbuser" | "mdb.host" | 3306 | null | "mdbdb" - - //https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url - "jdbc:microsoft:sqlserver://;" | null | "microsoft:sqlserver://localhost:1433" | "mssql" | "sqlserver" | null | "localhost" | 1433 | null | null - "jdbc:sqlserver://;serverName=3ffe:8311:eeee:f70f:0:5eae:10.203.31.9" | null | "sqlserver://[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]:1433" | "mssql" | null | null | "[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]" | 1433 | null | null - "jdbc:sqlserver://;serverName=2001:0db8:85a3:0000:0000:8a2e:0370:7334" | null | "sqlserver://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1433" | "mssql" | null | null | "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]" | 1433 | null | null - "jdbc:sqlserver://;serverName=[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]:43" | null | "sqlserver://[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]:43" | "mssql" | null | null | "[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]" | 43 | null | null - "jdbc:sqlserver://;serverName=3ffe:8311:eeee:f70f:0:5eae:10.203.31.9\\ssinstance" | null | "sqlserver://[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]:1433" | "mssql" | null | null | "[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]" | 1433 | "ssinstance" | null - "jdbc:sqlserver://;serverName=[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9\\ssinstance]:43" | null | "sqlserver://[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]:43" | "mssql" | null | null | "[3ffe:8311:eeee:f70f:0:5eae:10.203.31.9]" | 43 | "ssinstance" | null - "jdbc:microsoft:sqlserver://;" | stdProps | "microsoft:sqlserver://stdServerName:9999" | "mssql" | "sqlserver" | "stdUserName" | "stdServerName" | 9999 | null | "stdDatabaseName" - "jdbc:sqlserver://ss.host\\ssinstance:44;databaseName=ssdb;user=ssuser;password=pw" | null | "sqlserver://ss.host:44" | "mssql" | null | "ssuser" | "ss.host" | 44 | "ssinstance" | "ssdb" - "jdbc:sqlserver://;serverName=ss.host\\ssinstance:44;DatabaseName=;" | null | "sqlserver://ss.host:44" | "mssql" | null | null | "ss.host" | 44 | "ssinstance" | null - "jdbc:sqlserver://ss.host;serverName=althost;DatabaseName=ssdb;" | null | "sqlserver://ss.host:1433" | "mssql" | null | null | "ss.host" | 1433 | null | "ssdb" - "jdbc:microsoft:sqlserver://ss.host:44;DatabaseName=ssdb;user=ssuser;password=pw;user=ssuser2;" | null | "microsoft:sqlserver://ss.host:44" | "mssql" | "sqlserver" | "ssuser" | "ss.host" | 44 | null | "ssdb" - - // http://jtds.sourceforge.net/faq.html#urlFormat - "jdbc:jtds:sqlserver://ss.host/ssdb" | null | "jtds:sqlserver://ss.host:1433" | "mssql" | "sqlserver" | null | "ss.host" | 1433 | null | "ssdb" - "jdbc:jtds:sqlserver://ss.host:1433/ssdb" | null | "jtds:sqlserver://ss.host:1433" | "mssql" | "sqlserver" | null | "ss.host" | 1433 | null | "ssdb" - "jdbc:jtds:sqlserver://ss.host:1433/ssdb;user=ssuser" | null | "jtds:sqlserver://ss.host:1433" | "mssql" | "sqlserver" | "ssuser" | "ss.host" | 1433 | null | "ssdb" - "jdbc:jtds:sqlserver://ss.host:1433/ssdb;user=ssuser" | null | "jtds:sqlserver://ss.host:1433" | "mssql" | "sqlserver" | "ssuser" | "ss.host" | 1433 | null | "ssdb" - "jdbc:jtds:sqlserver://ss.host/ssdb;instance=ssinstance" | null | "jtds:sqlserver://ss.host:1433" | "mssql" | "sqlserver" | null | "ss.host" | 1433 | "ssinstance" | "ssdb" - "jdbc:jtds:sqlserver://ss.host:1444/ssdb;instance=ssinstance" | null | "jtds:sqlserver://ss.host:1444" | "mssql" | "sqlserver" | null | "ss.host" | 1444 | "ssinstance" | "ssdb" - "jdbc:jtds:sqlserver://ss.host:1433/ssdb;instance=ssinstance;user=ssuser" | null | "jtds:sqlserver://ss.host:1433" | "mssql" | "sqlserver" | "ssuser" | "ss.host" | 1433 | "ssinstance" | "ssdb" - - // https://docs.oracle.com/cd/B28359_01/java.111/b31224/urls.htm - // https://docs.oracle.com/cd/B28359_01/java.111/b31224/jdbcthin.htm - "jdbc:oracle:thin:orcluser/PW@localhost:55:orclsn" | null | "oracle:thin://localhost:55" | "oracle" | "thin" | "orcluser" | "localhost" | 55 | "orclsn" | null - "jdbc:oracle:thin:orcluser/PW@//orcl.host:55/orclsn" | null | "oracle:thin://orcl.host:55" | "oracle" | "thin" | "orcluser" | "orcl.host" | 55 | "orclsn" | null - "jdbc:oracle:thin:orcluser/PW@127.0.0.1:orclsn" | null | "oracle:thin://127.0.0.1:1521" | "oracle" | "thin" | "orcluser" | "127.0.0.1" | 1521 | "orclsn" | null - "jdbc:oracle:thin:orcluser/PW@//orcl.host/orclsn" | null | "oracle:thin://orcl.host:1521" | "oracle" | "thin" | "orcluser" | "orcl.host" | 1521 | "orclsn" | null - "jdbc:oracle:thin:@//orcl.host:55/orclsn" | null | "oracle:thin://orcl.host:55" | "oracle" | "thin" | null | "orcl.host" | 55 | "orclsn" | null - "jdbc:oracle:thin:@ldap://orcl.host:55/some,cn=OracleContext,dc=com" | null | "oracle:thin://orcl.host:55" | "oracle" | "thin" | null | "orcl.host" | 55 | "some,cn=oraclecontext,dc=com" | null - "jdbc:oracle:thin:127.0.0.1:orclsn" | null | "oracle:thin://127.0.0.1:1521" | "oracle" | "thin" | null | "127.0.0.1" | 1521 | "orclsn" | null - "jdbc:oracle:thin:orcl.host:orclsn" | stdProps | "oracle:thin://orcl.host:9999" | "oracle" | "thin" | "stdUserName" | "orcl.host" | 9999 | "orclsn" | "stdDatabaseName" - "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST= 127.0.0.1 )(POR T= 666))" + - "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orclsn)))" | null | "oracle:thin://127.0.0.1:1521" | "oracle" | "thin" | null | "127.0.0.1" | 1521 | "orclsn" | null - // https://docs.oracle.com/cd/B28359_01/java.111/b31224/instclnt.htm - "jdbc:oracle:drivertype:orcluser/PW@orcl.host:55/orclsn" | null | "oracle:drivertype://orcl.host:55" | "oracle" | "drivertype" | "orcluser" | "orcl.host" | 55 | "orclsn" | null - "jdbc:oracle:oci8:@" | null | "oracle:oci8:" | "oracle" | "oci8" | null | null | 1521 | null | null - "jdbc:oracle:oci8:@" | stdProps | "oracle:oci8://stdServerName:9999" | "oracle" | "oci8" | "stdUserName" | "stdServerName" | 9999 | null | "stdDatabaseName" - "jdbc:oracle:oci8:@orclsn" | null | "oracle:oci8:" | "oracle" | "oci8" | null | null | 1521 | "orclsn" | null - "jdbc:oracle:oci:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)( HOST = orcl.host )" + - "( PORT = 55 ))(CONNECT_DATA=(SERVICE_NAME =orclsn )))" | null | "oracle:oci://orcl.host:55" | "oracle" | "oci" | null | "orcl.host" | 55 | "orclsn" | null - - // https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/java/src/tpc/imjcc_tjvjcccn.html - // https://www.ibm.com/support/knowledgecenter/en/SSEPGG_10.5.0/com.ibm.db2.luw.apdv.java.doc/src /tpc/imjcc_r0052342.html - "jdbc:db2://db2.host" | null | "db2://db2.host:50000" | "db2" | null | null | "db2.host" | 50000 | null | null - "jdbc:db2://db2.host" | stdProps | "db2://db2.host:9999" | "db2" | null | "stdUserName" | "db2.host" | 9999 | null | "stdDatabaseName" - "jdbc:db2://db2.host:77/db2db:user=db2user;password=PW;" | null | "db2://db2.host:77" | "db2" | null | "db2user" | "db2.host" | 77 | "db2db" | null - "jdbc:db2://db2.host:77/db2db:user=db2user;password=PW;" | stdProps | "db2://db2.host:77" | "db2" | null | "db2user" | "db2.host" | 77 | "db2db" | "stdDatabaseName" - "jdbc:as400://ashost:66/asdb:user=asuser;password=PW;" | null | "as400://ashost:66" | "db2" | null | "asuser" | "ashost" | 66 | "asdb" | null - - // https://help.sap.com/viewer/0eec0d68141541d1b07893a39944924e/2.0.03/en-US/ff15928cf5594d78b841fbbe649f04b4.html - "jdbc:sap://sap.host" | null | "sap://sap.host" | "sap" | null | null | "sap.host" | null | null | null - "jdbc:sap://sap.host" | stdProps | "sap://sap.host:9999" | "sap" | null | "stdUserName" | "sap.host" | 9999 | null | "stdDatabaseName" - "jdbc:sap://sap.host:88/?databaseName=sapdb&user=sapuser&password=PW" | null | "sap://sap.host:88" | "sap" | null | "sapuser" | "sap.host" | 88 | null | "sapdb" - - // TODO: -// "jdbc:informix-sqli://infxhost:99/infxdb:INFORMIXSERVER=infxsn;user=infxuser;password=PW" | null | "informix-sqli" | null | "infxuser" | "infxhost" | 99 | "infxdb"| null -// "jdbc:informix-direct://infxdb:999;user=infxuser;password=PW" | null | "informix-direct" | null | "infxuser" | "infxhost" | 999 | "infxdb"| null - - // http://www.h2database.com/html/features.html#database_url - "jdbc:h2:mem:" | null | "h2:mem:" | "h2" | "mem" | null | null | null | null | null - "jdbc:h2:mem:" | stdProps | "h2:mem:" | "h2" | "mem" | "stdUserName" | null | null | null | "stdDatabaseName" - "jdbc:h2:mem:h2db" | null | "h2:mem:" | "h2" | "mem" | null | null | null | "h2db" | null - "jdbc:h2:tcp://h2.host:111/path/h2db;user=h2user;password=PW" | null | "h2:tcp://h2.host:111" | "h2" | "tcp" | "h2user" | "h2.host" | 111 | "path/h2db" | null - "jdbc:h2:ssl://h2.host:111/path/h2db;user=h2user;password=PW" | null | "h2:ssl://h2.host:111" | "h2" | "ssl" | "h2user" | "h2.host" | 111 | "path/h2db" | null - "jdbc:h2:/data/h2file" | null | "h2:file:" | "h2" | "file" | null | null | null | "/data/h2file" | null - "jdbc:h2:file:~/h2file;USER=h2user;PASSWORD=PW" | null | "h2:file:" | "h2" | "file" | null | null | null | "~/h2file" | null - "jdbc:h2:file:/data/h2file" | null | "h2:file:" | "h2" | "file" | null | null | null | "/data/h2file" | null - "jdbc:h2:file:C:/data/h2file" | null | "h2:file:" | "h2" | "file" | null | null | null | "c:/data/h2file" | null - "jdbc:h2:zip:~/db.zip!/h2zip" | null | "h2:zip:" | "h2" | "zip" | null | null | null | "~/db.zip!/h2zip" | null - - // http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html - "jdbc:hsqldb:hsdb" | null | "hsqldb:mem:" | "hsqldb" | "mem" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:hsdb" | stdProps | "hsqldb:mem:" | "hsqldb" | "mem" | "stdUserName" | null | null | "hsdb" | "stdDatabaseName" - "jdbc:hsqldb:mem:hsdb" | null | "hsqldb:mem:" | "hsqldb" | "mem" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:mem:hsdb;shutdown=true" | null | "hsqldb:mem:" | "hsqldb" | "mem" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:mem:hsdb?shutdown=true" | null | "hsqldb:mem:" | "hsqldb" | "mem" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:file:hsdb" | null | "hsqldb:file:" | "hsqldb" | "file" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:file:hsdb;user=aUserName;password=3xLVz" | null | "hsqldb:file:" | "hsqldb" | "file" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:file:hsdb;create=false?user=aUserName&password=3xLVz" | null | "hsqldb:file:" | "hsqldb" | "file" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:file:/loc/hsdb" | null | "hsqldb:file:" | "hsqldb" | "file" | "SA" | null | null | "/loc/hsdb" | null - "jdbc:hsqldb:file:C:/hsdb" | null | "hsqldb:file:" | "hsqldb" | "file" | "SA" | null | null | "c:/hsdb" | null - "jdbc:hsqldb:res:hsdb" | null | "hsqldb:res:" | "hsqldb" | "res" | "SA" | null | null | "hsdb" | null - "jdbc:hsqldb:res:/cp/hsdb" | null | "hsqldb:res:" | "hsqldb" | "res" | "SA" | null | null | "/cp/hsdb" | null - "jdbc:hsqldb:hsql://hs.host:333/hsdb" | null | "hsqldb:hsql://hs.host:333" | "hsqldb" | "hsql" | "SA" | "hs.host" | 333 | "hsdb" | null - "jdbc:hsqldb:hsqls://hs.host/hsdb" | null | "hsqldb:hsqls://hs.host:9001" | "hsqldb" | "hsqls" | "SA" | "hs.host" | 9001 | "hsdb" | null - "jdbc:hsqldb:http://hs.host" | null | "hsqldb:http://hs.host:80" | "hsqldb" | "http" | "SA" | "hs.host" | 80 | null | null - "jdbc:hsqldb:http://hs.host:333/hsdb" | null | "hsqldb:http://hs.host:333" | "hsqldb" | "http" | "SA" | "hs.host" | 333 | "hsdb" | null - "jdbc:hsqldb:https://127.0.0.1/hsdb" | null | "hsqldb:https://127.0.0.1:443" | "hsqldb" | "https" | "SA" | "127.0.0.1" | 443 | "hsdb" | null - - // https://db.apache.org/derby/papers/DerbyClientSpec.html#Connection+URL+Format - // https://db.apache.org/derby/docs/10.8/devguide/cdevdvlp34964.html - "jdbc:derby:derbydb" | null | "derby:directory:" | "derby" | "directory" | "APP" | null | null | "derbydb" | null - "jdbc:derby:derbydb" | stdProps | "derby:directory:" | "derby" | "directory" | "stdUserName" | null | null | "derbydb" | "stdDatabaseName" - "jdbc:derby:derbydb;user=derbyuser;password=pw" | null | "derby:directory:" | "derby" | "directory" | "derbyuser" | null | null | "derbydb" | null - "jdbc:derby:memory:derbydb" | null | "derby:memory:" | "derby" | "memory" | "APP" | null | null | "derbydb" | null - "jdbc:derby:memory:;databaseName=derbydb" | null | "derby:memory:" | "derby" | "memory" | "APP" | null | null | null | "derbydb" - "jdbc:derby:memory:derbydb;databaseName=altdb" | null | "derby:memory:" | "derby" | "memory" | "APP" | null | null | "derbydb" | "altdb" - "jdbc:derby:memory:derbydb;user=derbyuser;password=pw" | null | "derby:memory:" | "derby" | "memory" | "derbyuser" | null | null | "derbydb" | null - "jdbc:derby://derby.host:222/memory:derbydb;create=true" | null | "derby:network://derby.host:222" | "derby" | "network" | "APP" | "derby.host" | 222 | "derbydb" | null - "jdbc:derby://derby.host/memory:derbydb;create=true;user=derbyuser;password=pw" | null | "derby:network://derby.host:1527" | "derby" | "network" | "derbyuser" | "derby.host" | 1527 | "derbydb" | null - "jdbc:derby://127.0.0.1:1527/memory:derbydb;create=true;user=derbyuser;password=pw" | null | "derby:network://127.0.0.1:1527" | "derby" | "network" | "derbyuser" | "127.0.0.1" | 1527 | "derbydb" | null - "jdbc:derby:directory:derbydb;user=derbyuser;password=pw" | null | "derby:directory:" | "derby" | "directory" | "derbyuser" | null | null | "derbydb" | null - "jdbc:derby:classpath:/some/derbydb;user=derbyuser;password=pw" | null | "derby:classpath:" | "derby" | "classpath" | "derbyuser" | null | null | "/some/derbydb" | null - "jdbc:derby:jar:/derbydb;user=derbyuser;password=pw" | null | "derby:jar:" | "derby" | "jar" | "derbyuser" | null | null | "/derbydb" | null - "jdbc:derby:jar:(~/path/to/db.jar)/other/derbydb;user=derbyuser;password=pw" | null | "derby:jar:" | "derby" | "jar" | "derbyuser" | null | null | "(~/path/to/db.jar)/other/derbydb" | null - - expected = new DbInfo.Builder().system(system).subtype(subtype).user(user).name(name).db(db).host(host).port(port).shortUrl(shortUrl).build() - } -} diff --git a/instrumentation/jdbc/src/test/groovy/JdbcInstrumentationTest.groovy b/instrumentation/jdbc/src/test/groovy/JdbcInstrumentationTest.groovy deleted file mode 100644 index a52558a61c..0000000000 --- a/instrumentation/jdbc/src/test/groovy/JdbcInstrumentationTest.groovy +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.mchange.v2.c3p0.ComboPooledDataSource -import com.zaxxer.hikari.HikariConfig -import com.zaxxer.hikari.HikariDataSource -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import io.opentelemetry.javaagent.instrumentation.jdbc.JdbcUtils -import java.sql.CallableStatement -import java.sql.Connection -import java.sql.PreparedStatement -import java.sql.ResultSet -import java.sql.Statement -import javax.sql.DataSource -import org.apache.derby.jdbc.EmbeddedDataSource -import org.apache.derby.jdbc.EmbeddedDriver -import org.h2.Driver -import org.h2.jdbcx.JdbcDataSource -import org.hsqldb.jdbc.JDBCDriver -import spock.lang.Shared -import spock.lang.Unroll -import test.TestConnection -import test.TestDriver - -class JdbcInstrumentationTest extends AgentTestRunner { - static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { - it.setProperty("otel.instrumentation.jdbc-datasource.enabled", "true") - } - - def specCleanup() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - @Shared - def dbName = "jdbcUnitTest" - @Shared - def dbNameLower = dbName.toLowerCase() - - @Shared - private Map jdbcUrls = [ - "h2" : "jdbc:h2:mem:$dbName", - "derby" : "jdbc:derby:memory:$dbName", - "hsqldb": "jdbc:hsqldb:mem:$dbName", - ] - - @Shared - private Map jdbcDriverClassNames = [ - "h2" : "org.h2.Driver", - "derby" : "org.apache.derby.jdbc.EmbeddedDriver", - "hsqldb": "org.hsqldb.jdbc.JDBCDriver", - ] - - @Shared - private Map jdbcUserNames = [ - "h2" : null, - "derby" : "APP", - "hsqldb": "SA", - ] - - @Shared - private Properties connectionProps = { - def props = new Properties() -// props.put("user", "someUser") -// props.put("password", "somePassword") - props.put("databaseName", "someDb") - props.put("OPEN_NEW", "true") // So H2 doesn't complain about username/password. - return props - }() - - // JDBC Connection pool name (i.e. HikariCP) -> Map - @Shared - private Map> cpDatasources = new HashMap<>() - - def prepareConnectionPoolDatasources() { - String[] connectionPoolNames = [ - "tomcat", "hikari", "c3p0", - ] - connectionPoolNames.each { - cpName -> - Map dbDSMapping = new HashMap<>() - jdbcUrls.each { - dbType, jdbcUrl -> - dbDSMapping.put(dbType, createDS(cpName, dbType, jdbcUrl)) - } - cpDatasources.put(cpName, dbDSMapping) - } - } - - def createTomcatDS(String dbType, String jdbcUrl) { - DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource() - def jdbcUrlToSet = dbType == "derby" ? jdbcUrl + ";create=true" : jdbcUrl - ds.setUrl(jdbcUrlToSet) - ds.setDriverClassName(jdbcDriverClassNames.get(dbType)) - String username = jdbcUserNames.get(dbType) - if (username != null) { - ds.setUsername(username) - } - ds.setPassword("") - ds.setMaxActive(1) // to test proper caching, having > 1 max active connection will be hard to - // determine whether the connection is properly cached - return ds - } - - def createHikariDS(String dbType, String jdbcUrl) { - HikariConfig config = new HikariConfig() - def jdbcUrlToSet = dbType == "derby" ? jdbcUrl + ";create=true" : jdbcUrl - config.setJdbcUrl(jdbcUrlToSet) - String username = jdbcUserNames.get(dbType) - if (username != null) { - config.setUsername(username) - } - config.setPassword("") - config.addDataSourceProperty("cachePrepStmts", "true") - config.addDataSourceProperty("prepStmtCacheSize", "250") - config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048") - config.setMaximumPoolSize(1) - - return new HikariDataSource(config) - } - - def createC3P0DS(String dbType, String jdbcUrl) { - DataSource ds = new ComboPooledDataSource() - ds.setDriverClass(jdbcDriverClassNames.get(dbType)) - def jdbcUrlToSet = dbType == "derby" ? jdbcUrl + ";create=true" : jdbcUrl - ds.setJdbcUrl(jdbcUrlToSet) - String username = jdbcUserNames.get(dbType) - if (username != null) { - ds.setUser(username) - } - ds.setPassword("") - ds.setMaxPoolSize(1) - return ds - } - - def createDS(String connectionPoolName, String dbType, String jdbcUrl) { - DataSource ds = null - if (connectionPoolName == "tomcat") { - ds = createTomcatDS(dbType, jdbcUrl) - } - if (connectionPoolName == "hikari") { - ds = createHikariDS(dbType, jdbcUrl) - } - if (connectionPoolName == "c3p0") { - ds = createC3P0DS(dbType, jdbcUrl) - } - return ds - } - - def setupSpec() { - prepareConnectionPoolDatasources() - } - - def cleanupSpec() { - cpDatasources.values().each { - it.values().each { - datasource -> - if (datasource instanceof Closeable) { - datasource.close() - } - } - } - } - - @Unroll - def "basic statement with #connection.getClass().getCanonicalName() on #driver generates spans"() { - setup: - Statement statement = connection.createStatement() - ResultSet resultSet = runUnderTrace("parent") { - return statement.executeQuery(query) - } - - expect: - resultSet.next() - resultSet.getInt(1) == 3 - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name spanName - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbNameLower - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement.close() - connection.close() - - where: - system | connection | username | query | spanName | url - "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), null) | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" | "SELECT ${dbNameLower}.INFORMATION_SCHEMA.SYSTEM_USERS" | "hsqldb:mem:" - "h2" | new Driver().connect(jdbcUrls.get("h2"), connectionProps) | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), connectionProps) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), connectionProps) | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" | "SELECT ${dbNameLower}.INFORMATION_SCHEMA.SYSTEM_USERS" | "hsqldb:mem:" - "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "hsqldb" | cpDatasources.get("tomcat").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" | "SELECT ${dbNameLower}.INFORMATION_SCHEMA.SYSTEM_USERS" | "hsqldb:mem:" - "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "hsqldb" | cpDatasources.get("hikari").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" | "SELECT ${dbNameLower}.INFORMATION_SCHEMA.SYSTEM_USERS" | "hsqldb:mem:" - "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "hsqldb" | cpDatasources.get("c3p0").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" | "SELECT ${dbNameLower}.INFORMATION_SCHEMA.SYSTEM_USERS" | "hsqldb:mem:" - } - - @Unroll - def "prepared statement execute on #driver with #connection.getClass().getCanonicalName() generates a span"() { - setup: - PreparedStatement statement = connection.prepareStatement(query) - ResultSet resultSet = runUnderTrace("parent") { - assert statement.execute() - return statement.resultSet - } - - expect: - resultSet.next() - resultSet.getInt(1) == 3 - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name spanName - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbNameLower - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement.close() - connection.close() - - where: - system | connection | username | query | spanName | url - "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - } - - @Unroll - def "prepared statement query on #driver with #connection.getClass().getCanonicalName() generates a span"() { - setup: - PreparedStatement statement = connection.prepareStatement(query) - ResultSet resultSet = runUnderTrace("parent") { - return statement.executeQuery() - } - - expect: - resultSet.next() - resultSet.getInt(1) == 3 - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name spanName - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbNameLower - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement.close() - connection.close() - - where: - system | connection | username | query | spanName | url - "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - } - - @Unroll - def "prepared call on #driver with #connection.getClass().getCanonicalName() generates a span"() { - setup: - CallableStatement statement = connection.prepareCall(query) - ResultSet resultSet = runUnderTrace("parent") { - return statement.executeQuery() - } - - expect: - resultSet.next() - resultSet.getInt(1) == 3 - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name spanName - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbName.toLowerCase() - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement.close() - connection.close() - - where: - system | connection | username | query | spanName | url - "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" | "SELECT $dbNameLower" | "h2:mem:" - "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - } - - @Unroll - def "statement update on #driver with #connection.getClass().getCanonicalName() generates a span"() { - setup: - Statement statement = connection.createStatement() - def sql = connection.nativeSQL(query) - - expect: - runUnderTrace("parent") { - return !statement.execute(sql) - } - statement.updateCount == 0 - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name dbNameLower - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbNameLower - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement.close() - connection.close() - - where: - system | connection | username | query | url - "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "CREATE TABLE S_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "CREATE TABLE S_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), null) | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB (id INTEGER not NULL, PRIMARY KEY ( id ))" | "hsqldb:mem:" - "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "CREATE TABLE S_H2_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "hsqldb" | cpDatasources.get("tomcat").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" | "hsqldb:mem:" - "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "CREATE TABLE S_H2_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "hsqldb" | cpDatasources.get("hikari").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" | "hsqldb:mem:" - "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE S_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "hsqldb" | cpDatasources.get("c3p0").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "hsqldb:mem:" - } - - @Unroll - def "prepared statement update on #driver with #connection.getClass().getCanonicalName() generates a span"() { - setup: - def sql = connection.nativeSQL(query) - PreparedStatement statement = connection.prepareStatement(sql) - - expect: - runUnderTrace("parent") { - return statement.executeUpdate() == 0 - } - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name dbNameLower - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbName.toLowerCase() - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement.close() - connection.close() - - where: - system | connection | username | query | url - "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "CREATE TABLE PS_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "CREATE TABLE PS_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "CREATE TABLE PS_H2_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "CREATE TABLE PS_H2_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE PS_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "h2:mem:" - "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" | "derby:memory:" - } - - @Unroll - def "connection constructor throwing then generating correct spans after recovery using #driver connection (prepare statement = #prepareStatement)"() { - setup: - Connection connection = null - - when: - try { - connection = new TestConnection(true) - } catch (Exception ignored) { - connection = driver.connect(jdbcUrl, null) - } - - def (Statement statement, ResultSet rs) = runUnderTrace("parent") { - if (prepareStatement) { - def statement = connection.prepareStatement(query) - return new Tuple(statement, statement.executeQuery()) - } - - def statement = connection.createStatement() - return new Tuple(statement, statement.executeQuery(query)) - } - - then: - rs.next() - rs.getInt(1) == 3 - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name spanName - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" system - "$SemanticAttributes.DB_NAME.key" dbNameLower - if (username != null) { - "$SemanticAttributes.DB_USER.key" username - } - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" url - } - } - } - } - - cleanup: - statement?.close() - connection?.close() - - where: - prepareStatement | system | driver | jdbcUrl | username | query | spanName | url - true | "h2" | new Driver() | "jdbc:h2:mem:" + dbName | null | "SELECT 3;" | "SELECT $dbNameLower" | "h2:mem:" - true | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - false | "h2" | new Driver() | "jdbc:h2:mem:" + dbName | null | "SELECT 3;" | "SELECT $dbNameLower" | "h2:mem:" - false | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" | "SELECT ${dbNameLower}.SYSIBM.SYSDUMMY1" | "derby:memory:" - } - - def "calling #datasource.class.simpleName getConnection generates a span when under existing trace"() { - setup: - assert datasource instanceof DataSource - init?.call(datasource) - - when: - datasource.getConnection().close() - - then: - !TEST_WRITER.traces.any { it.any { it.name == "database.connection" } } - TEST_WRITER.clear() - - when: - runUnderTrace("parent") { - datasource.getConnection().close() - } - - then: - assertTraces(1) { - trace(0, recursive ? 3 : 2) { - basicSpan(it, 0, "parent") - - span(1) { - name "${datasource.class.simpleName}.getConnection" - childOf span(0) - attributes { - } - } - if (recursive) { - span(2) { - name "${datasource.class.simpleName}.getConnection" - childOf span(1) - attributes { - } - } - } - } - } - - where: - datasource | init - new JdbcDataSource() | { ds -> ds.setURL(jdbcUrls.get("h2")) } - new EmbeddedDataSource() | { ds -> ds.jdbcurl = jdbcUrls.get("derby") } - cpDatasources.get("hikari").get("h2") | null - cpDatasources.get("hikari").get("derby") | null - cpDatasources.get("c3p0").get("h2") | null - cpDatasources.get("c3p0").get("derby") | null - - // Tomcat's pool doesn't work because the getConnection method is - // implemented in a parent class that doesn't implement DataSource - - recursive = datasource instanceof EmbeddedDataSource - } - - def "test getClientInfo exception"() { - setup: - Connection connection = new TestConnection(false) - - when: - Statement statement = null - runUnderTrace("parent") { - statement = connection.createStatement() - return statement.executeQuery(query) - } - - then: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name "DB Query" - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "testdb" - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" "testdb://localhost" - } - } - } - } - - cleanup: - statement?.close() - connection?.close() - - where: - query = "testing 123" - } - - @Unroll - def "should produce proper span name #spanName"() { - setup: - def driver = new TestDriver() - - when: - def connection = driver.connect(url, null) - runUnderTrace("parent") { - def statement = connection.createStatement() - return statement.executeQuery(query) - } - - then: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - span(1) { - name spanName - kind CLIENT - childOf span(0) - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "testdb" - "$SemanticAttributes.DB_NAME.key" databaseName - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" "testdb://localhost" - } - } - } - } - - where: - url | query | spanName | databaseName - "jdbc:testdb://localhost?databaseName=test" | "SELECT * FROM table" | "SELECT test.table" | "test" - "jdbc:testdb://localhost?databaseName=test" | "SELECT 42" | "SELECT test" | "test" - "jdbc:testdb://localhost" | "SELECT * FROM table" | "SELECT table" | null - "jdbc:testdb://localhost?databaseName=test" | "CREATE TABLE table" | "test" | "test" - "jdbc:testdb://localhost" | "CREATE TABLE table" | "DB Query" | null - } - - @Unroll - def "#connectionPoolName connections should be cached in case of wrapped connections"() { - setup: - String dbType = "hsqldb" - DataSource ds = createDS(connectionPoolName, dbType, jdbcUrls.get(dbType)) - String query = "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" - int numQueries = 5 - Connection connection = null - int[] res = new int[numQueries] - - when: - for (int i = 0; i < numQueries; ++i) { - try { - connection = ds.getConnection() - def statement = connection.prepareStatement(query) - def rs = statement.executeQuery() - if (rs.next()) { - res[i] = rs.getInt(1) - } else { - res[i] = 0 - } - } finally { - connection.close() - } - } - - then: - for (int i = 0; i < numQueries; ++i) { - res[i] == 3 - } - assertTraces(numQueries) { - for (int i = 0; i < numQueries; ++i) { - trace(i, 1) { - span(0) { - name "SELECT ${dbNameLower}.INFORMATION_SCHEMA.SYSTEM_USERS" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "hsqldb" - "$SemanticAttributes.DB_NAME.key" dbNameLower - "$SemanticAttributes.DB_USER.key" "SA" - "$SemanticAttributes.DB_STATEMENT.key" JdbcUtils.normalizeSql(query) - "$SemanticAttributes.DB_CONNECTION_STRING.key" "hsqldb:mem:" - } - } - } - } - } - - cleanup: - if (ds instanceof Closeable) { - ds.close() - } - - where: - connectionPoolName | _ - "hikari" | _ - "tomcat" | _ - "c3p0" | _ - } -} diff --git a/instrumentation/jdbc/src/test/groovy/test/TestConnection.groovy b/instrumentation/jdbc/src/test/groovy/test/TestConnection.groovy deleted file mode 100644 index edfe44c746..0000000000 --- a/instrumentation/jdbc/src/test/groovy/test/TestConnection.groovy +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import java.sql.Array -import java.sql.Blob -import java.sql.CallableStatement -import java.sql.Clob -import java.sql.Connection -import java.sql.DatabaseMetaData -import java.sql.NClob -import java.sql.PreparedStatement -import java.sql.SQLClientInfoException -import java.sql.SQLException -import java.sql.SQLWarning -import java.sql.SQLXML -import java.sql.Savepoint -import java.sql.Statement -import java.sql.Struct -import java.util.concurrent.Executor - - -/** - * A JDBC connection class that optionally throws an exception in the constructor, used to test - */ -class TestConnection implements Connection { - TestConnection(boolean throwException) { - if (throwException) { - throw new RuntimeException("connection exception") - } - } - - - @Override - Statement createStatement() throws SQLException { - return new TestStatement(this) - } - - @Override - PreparedStatement prepareStatement(String sql) throws SQLException { - return null - } - - @Override - CallableStatement prepareCall(String sql) throws SQLException { - return null - } - - @Override - String nativeSQL(String sql) throws SQLException { - return null - } - - @Override - void setAutoCommit(boolean autoCommit) throws SQLException { - - } - - @Override - boolean getAutoCommit() throws SQLException { - return false - } - - @Override - void commit() throws SQLException { - - } - - @Override - void rollback() throws SQLException { - - } - - @Override - void close() throws SQLException { - - } - - @Override - boolean isClosed() throws SQLException { - return false - } - - @Override - DatabaseMetaData getMetaData() throws SQLException { - return new TestDatabaseMetaData() - } - - @Override - void setReadOnly(boolean readOnly) throws SQLException { - - } - - @Override - boolean isReadOnly() throws SQLException { - return false - } - - @Override - void setCatalog(String catalog) throws SQLException { - - } - - @Override - String getCatalog() throws SQLException { - return null - } - - @Override - void setTransactionIsolation(int level) throws SQLException { - - } - - @Override - int getTransactionIsolation() throws SQLException { - return 0 - } - - @Override - SQLWarning getWarnings() throws SQLException { - return null - } - - @Override - void clearWarnings() throws SQLException { - - } - - @Override - Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - return null - } - - @Override - PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return null - } - - @Override - CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return null - } - - @Override - Map> getTypeMap() throws SQLException { - return null - } - - @Override - void setTypeMap(Map> map) throws SQLException { - - } - - @Override - void setHoldability(int holdability) throws SQLException { - - } - - @Override - int getHoldability() throws SQLException { - return 0 - } - - @Override - Savepoint setSavepoint() throws SQLException { - return null - } - - @Override - Savepoint setSavepoint(String name) throws SQLException { - return null - } - - @Override - void rollback(Savepoint savepoint) throws SQLException { - - } - - @Override - void releaseSavepoint(Savepoint savepoint) throws SQLException { - - } - - @Override - Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return null - } - - @Override - PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return null - } - - @Override - CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return null - } - - @Override - PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - return null - } - - @Override - PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - return null - } - - @Override - PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - return null - } - - @Override - Clob createClob() throws SQLException { - return null - } - - @Override - Blob createBlob() throws SQLException { - return null - } - - @Override - NClob createNClob() throws SQLException { - return null - } - - @Override - SQLXML createSQLXML() throws SQLException { - return null - } - - @Override - boolean isValid(int timeout) throws SQLException { - return false - } - - @Override - void setClientInfo(String name, String value) throws SQLClientInfoException { - - } - - @Override - void setClientInfo(Properties properties) throws SQLClientInfoException { - - } - - @Override - String getClientInfo(String name) throws SQLException { - throw new UnsupportedOperationException("Test 123") - } - - @Override - Properties getClientInfo() throws SQLException { - throw new Throwable("Test 123") - } - - @Override - Array createArrayOf(String typeName, Object[] elements) throws SQLException { - return null - } - - @Override - Struct createStruct(String typeName, Object[] attributes) throws SQLException { - return null - } - - @Override - void setSchema(String schema) throws SQLException { - - } - - @Override - String getSchema() throws SQLException { - return null - } - - @Override - void abort(Executor executor) throws SQLException { - - } - - @Override - void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { - - } - - @Override - int getNetworkTimeout() throws SQLException { - return 0 - } - - @Override - def T unwrap(Class iface) throws SQLException { - return null - } - - @Override - boolean isWrapperFor(Class iface) throws SQLException { - return false - } -} diff --git a/instrumentation/jdbc/src/test/groovy/test/TestDatabaseMetaData.groovy b/instrumentation/jdbc/src/test/groovy/test/TestDatabaseMetaData.groovy deleted file mode 100644 index 757b43a2df..0000000000 --- a/instrumentation/jdbc/src/test/groovy/test/TestDatabaseMetaData.groovy +++ /dev/null @@ -1,894 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import java.sql.Connection -import java.sql.DatabaseMetaData -import java.sql.ResultSet -import java.sql.RowIdLifetime -import java.sql.SQLException - -class TestDatabaseMetaData implements DatabaseMetaData { - @Override - boolean allProceduresAreCallable() throws SQLException { - return false - } - - @Override - boolean allTablesAreSelectable() throws SQLException { - return false - } - - @Override - String getURL() throws SQLException { - return "jdbc:testdb://localhost" - } - - @Override - String getUserName() throws SQLException { - return null - } - - @Override - boolean isReadOnly() throws SQLException { - return false - } - - @Override - boolean nullsAreSortedHigh() throws SQLException { - return false - } - - @Override - boolean nullsAreSortedLow() throws SQLException { - return false - } - - @Override - boolean nullsAreSortedAtStart() throws SQLException { - return false - } - - @Override - boolean nullsAreSortedAtEnd() throws SQLException { - return false - } - - @Override - String getDatabaseProductName() throws SQLException { - return null - } - - @Override - String getDatabaseProductVersion() throws SQLException { - return null - } - - @Override - String getDriverName() throws SQLException { - return null - } - - @Override - String getDriverVersion() throws SQLException { - return null - } - - @Override - int getDriverMajorVersion() { - return 0 - } - - @Override - int getDriverMinorVersion() { - return 0 - } - - @Override - boolean usesLocalFiles() throws SQLException { - return false - } - - @Override - boolean usesLocalFilePerTable() throws SQLException { - return false - } - - @Override - boolean supportsMixedCaseIdentifiers() throws SQLException { - return false - } - - @Override - boolean storesUpperCaseIdentifiers() throws SQLException { - return false - } - - @Override - boolean storesLowerCaseIdentifiers() throws SQLException { - return false - } - - @Override - boolean storesMixedCaseIdentifiers() throws SQLException { - return false - } - - @Override - boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { - return false - } - - @Override - boolean storesUpperCaseQuotedIdentifiers() throws SQLException { - return false - } - - @Override - boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - return false - } - - @Override - boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - return false - } - - @Override - String getIdentifierQuoteString() throws SQLException { - return null - } - - @Override - String getSQLKeywords() throws SQLException { - return null - } - - @Override - String getNumericFunctions() throws SQLException { - return null - } - - @Override - String getStringFunctions() throws SQLException { - return null - } - - @Override - String getSystemFunctions() throws SQLException { - return null - } - - @Override - String getTimeDateFunctions() throws SQLException { - return null - } - - @Override - String getSearchStringEscape() throws SQLException { - return null - } - - @Override - String getExtraNameCharacters() throws SQLException { - return null - } - - @Override - boolean supportsAlterTableWithAddColumn() throws SQLException { - return false - } - - @Override - boolean supportsAlterTableWithDropColumn() throws SQLException { - return false - } - - @Override - boolean supportsColumnAliasing() throws SQLException { - return false - } - - @Override - boolean nullPlusNonNullIsNull() throws SQLException { - return false - } - - @Override - boolean supportsConvert() throws SQLException { - return false - } - - @Override - boolean supportsConvert(int fromType, int toType) throws SQLException { - return false - } - - @Override - boolean supportsTableCorrelationNames() throws SQLException { - return false - } - - @Override - boolean supportsDifferentTableCorrelationNames() throws SQLException { - return false - } - - @Override - boolean supportsExpressionsInOrderBy() throws SQLException { - return false - } - - @Override - boolean supportsOrderByUnrelated() throws SQLException { - return false - } - - @Override - boolean supportsGroupBy() throws SQLException { - return false - } - - @Override - boolean supportsGroupByUnrelated() throws SQLException { - return false - } - - @Override - boolean supportsGroupByBeyondSelect() throws SQLException { - return false - } - - @Override - boolean supportsLikeEscapeClause() throws SQLException { - return false - } - - @Override - boolean supportsMultipleResultSets() throws SQLException { - return false - } - - @Override - boolean supportsMultipleTransactions() throws SQLException { - return false - } - - @Override - boolean supportsNonNullableColumns() throws SQLException { - return false - } - - @Override - boolean supportsMinimumSQLGrammar() throws SQLException { - return false - } - - @Override - boolean supportsCoreSQLGrammar() throws SQLException { - return false - } - - @Override - boolean supportsExtendedSQLGrammar() throws SQLException { - return false - } - - @Override - boolean supportsANSI92EntryLevelSQL() throws SQLException { - return false - } - - @Override - boolean supportsANSI92IntermediateSQL() throws SQLException { - return false - } - - @Override - boolean supportsANSI92FullSQL() throws SQLException { - return false - } - - @Override - boolean supportsIntegrityEnhancementFacility() throws SQLException { - return false - } - - @Override - boolean supportsOuterJoins() throws SQLException { - return false - } - - @Override - boolean supportsFullOuterJoins() throws SQLException { - return false - } - - @Override - boolean supportsLimitedOuterJoins() throws SQLException { - return false - } - - @Override - String getSchemaTerm() throws SQLException { - return null - } - - @Override - String getProcedureTerm() throws SQLException { - return null - } - - @Override - String getCatalogTerm() throws SQLException { - return null - } - - @Override - boolean isCatalogAtStart() throws SQLException { - return false - } - - @Override - String getCatalogSeparator() throws SQLException { - return null - } - - @Override - boolean supportsSchemasInDataManipulation() throws SQLException { - return false - } - - @Override - boolean supportsSchemasInProcedureCalls() throws SQLException { - return false - } - - @Override - boolean supportsSchemasInTableDefinitions() throws SQLException { - return false - } - - @Override - boolean supportsSchemasInIndexDefinitions() throws SQLException { - return false - } - - @Override - boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { - return false - } - - @Override - boolean supportsCatalogsInDataManipulation() throws SQLException { - return false - } - - @Override - boolean supportsCatalogsInProcedureCalls() throws SQLException { - return false - } - - @Override - boolean supportsCatalogsInTableDefinitions() throws SQLException { - return false - } - - @Override - boolean supportsCatalogsInIndexDefinitions() throws SQLException { - return false - } - - @Override - boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { - return false - } - - @Override - boolean supportsPositionedDelete() throws SQLException { - return false - } - - @Override - boolean supportsPositionedUpdate() throws SQLException { - return false - } - - @Override - boolean supportsSelectForUpdate() throws SQLException { - return false - } - - @Override - boolean supportsStoredProcedures() throws SQLException { - return false - } - - @Override - boolean supportsSubqueriesInComparisons() throws SQLException { - return false - } - - @Override - boolean supportsSubqueriesInExists() throws SQLException { - return false - } - - @Override - boolean supportsSubqueriesInIns() throws SQLException { - return false - } - - @Override - boolean supportsSubqueriesInQuantifieds() throws SQLException { - return false - } - - @Override - boolean supportsCorrelatedSubqueries() throws SQLException { - return false - } - - @Override - boolean supportsUnion() throws SQLException { - return false - } - - @Override - boolean supportsUnionAll() throws SQLException { - return false - } - - @Override - boolean supportsOpenCursorsAcrossCommit() throws SQLException { - return false - } - - @Override - boolean supportsOpenCursorsAcrossRollback() throws SQLException { - return false - } - - @Override - boolean supportsOpenStatementsAcrossCommit() throws SQLException { - return false - } - - @Override - boolean supportsOpenStatementsAcrossRollback() throws SQLException { - return false - } - - @Override - int getMaxBinaryLiteralLength() throws SQLException { - return 0 - } - - @Override - int getMaxCharLiteralLength() throws SQLException { - return 0 - } - - @Override - int getMaxColumnNameLength() throws SQLException { - return 0 - } - - @Override - int getMaxColumnsInGroupBy() throws SQLException { - return 0 - } - - @Override - int getMaxColumnsInIndex() throws SQLException { - return 0 - } - - @Override - int getMaxColumnsInOrderBy() throws SQLException { - return 0 - } - - @Override - int getMaxColumnsInSelect() throws SQLException { - return 0 - } - - @Override - int getMaxColumnsInTable() throws SQLException { - return 0 - } - - @Override - int getMaxConnections() throws SQLException { - return 0 - } - - @Override - int getMaxCursorNameLength() throws SQLException { - return 0 - } - - @Override - int getMaxIndexLength() throws SQLException { - return 0 - } - - @Override - int getMaxSchemaNameLength() throws SQLException { - return 0 - } - - @Override - int getMaxProcedureNameLength() throws SQLException { - return 0 - } - - @Override - int getMaxCatalogNameLength() throws SQLException { - return 0 - } - - @Override - int getMaxRowSize() throws SQLException { - return 0 - } - - @Override - boolean doesMaxRowSizeIncludeBlobs() throws SQLException { - return false - } - - @Override - int getMaxStatementLength() throws SQLException { - return 0 - } - - @Override - int getMaxStatements() throws SQLException { - return 0 - } - - @Override - int getMaxTableNameLength() throws SQLException { - return 0 - } - - @Override - int getMaxTablesInSelect() throws SQLException { - return 0 - } - - @Override - int getMaxUserNameLength() throws SQLException { - return 0 - } - - @Override - int getDefaultTransactionIsolation() throws SQLException { - return 0 - } - - @Override - boolean supportsTransactions() throws SQLException { - return false - } - - @Override - boolean supportsTransactionIsolationLevel(int level) throws SQLException { - return false - } - - @Override - boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { - return false - } - - @Override - boolean supportsDataManipulationTransactionsOnly() throws SQLException { - return false - } - - @Override - boolean dataDefinitionCausesTransactionCommit() throws SQLException { - return false - } - - @Override - boolean dataDefinitionIgnoredInTransactions() throws SQLException { - return false - } - - @Override - ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { - return null - } - - @Override - ResultSet getSchemas() throws SQLException { - return null - } - - @Override - ResultSet getCatalogs() throws SQLException { - return null - } - - @Override - ResultSet getTableTypes() throws SQLException { - return null - } - - @Override - ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { - return null - } - - @Override - ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { - return null - } - - @Override - ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { - return null - } - - @Override - ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { - return null - } - - @Override - ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { - return null - } - - @Override - ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { - return null - } - - @Override - ResultSet getTypeInfo() throws SQLException { - return null - } - - @Override - ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { - return null - } - - @Override - boolean supportsResultSetType(int type) throws SQLException { - return false - } - - @Override - boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { - return false - } - - @Override - boolean ownUpdatesAreVisible(int type) throws SQLException { - return false - } - - @Override - boolean ownDeletesAreVisible(int type) throws SQLException { - return false - } - - @Override - boolean ownInsertsAreVisible(int type) throws SQLException { - return false - } - - @Override - boolean othersUpdatesAreVisible(int type) throws SQLException { - return false - } - - @Override - boolean othersDeletesAreVisible(int type) throws SQLException { - return false - } - - @Override - boolean othersInsertsAreVisible(int type) throws SQLException { - return false - } - - @Override - boolean updatesAreDetected(int type) throws SQLException { - return false - } - - @Override - boolean deletesAreDetected(int type) throws SQLException { - return false - } - - @Override - boolean insertsAreDetected(int type) throws SQLException { - return false - } - - @Override - boolean supportsBatchUpdates() throws SQLException { - return false - } - - @Override - ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { - return null - } - - @Override - Connection getConnection() throws SQLException { - return null - } - - @Override - boolean supportsSavepoints() throws SQLException { - return false - } - - @Override - boolean supportsNamedParameters() throws SQLException { - return false - } - - @Override - boolean supportsMultipleOpenResults() throws SQLException { - return false - } - - @Override - boolean supportsGetGeneratedKeys() throws SQLException { - return false - } - - @Override - ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { - return null - } - - @Override - boolean supportsResultSetHoldability(int holdability) throws SQLException { - return false - } - - @Override - int getResultSetHoldability() throws SQLException { - return 0 - } - - @Override - int getDatabaseMajorVersion() throws SQLException { - return 0 - } - - @Override - int getDatabaseMinorVersion() throws SQLException { - return 0 - } - - @Override - int getJDBCMajorVersion() throws SQLException { - return 0 - } - - @Override - int getJDBCMinorVersion() throws SQLException { - return 0 - } - - @Override - int getSQLStateType() throws SQLException { - return 0 - } - - @Override - boolean locatorsUpdateCopy() throws SQLException { - return false - } - - @Override - boolean supportsStatementPooling() throws SQLException { - return false - } - - @Override - RowIdLifetime getRowIdLifetime() throws SQLException { - return null - } - - @Override - ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { - return null - } - - @Override - boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { - return false - } - - @Override - boolean autoCommitFailureClosesAllResultSets() throws SQLException { - return false - } - - @Override - ResultSet getClientInfoProperties() throws SQLException { - return null - } - - @Override - ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { - return null - } - - @Override - ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { - return null - } - - @Override - boolean generatedKeyAlwaysReturned() throws SQLException { - return false - } - - @Override - def T unwrap(Class iface) throws SQLException { - return null - } - - @Override - boolean isWrapperFor(Class iface) throws SQLException { - return false - } -} diff --git a/instrumentation/jdbc/src/test/groovy/test/TestDriver.groovy b/instrumentation/jdbc/src/test/groovy/test/TestDriver.groovy deleted file mode 100644 index 60b2368bac..0000000000 --- a/instrumentation/jdbc/src/test/groovy/test/TestDriver.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import java.sql.Connection -import java.sql.Driver -import java.sql.DriverPropertyInfo -import java.sql.SQLException -import java.sql.SQLFeatureNotSupportedException -import java.util.logging.Logger - -class TestDriver implements Driver { - @Override - Connection connect(String url, Properties info) throws SQLException { - return new TestConnection("connectException=true" == url) - } - - @Override - boolean acceptsURL(String url) throws SQLException { - return false - } - - @Override - DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { - return new DriverPropertyInfo[0] - } - - @Override - int getMajorVersion() { - return 0 - } - - @Override - int getMinorVersion() { - return 0 - } - - @Override - boolean jdbcCompliant() { - return false - } - - @Override - Logger getParentLogger() throws SQLFeatureNotSupportedException { - return null - } -} diff --git a/instrumentation/jdbc/src/test/groovy/test/TestStatement.groovy b/instrumentation/jdbc/src/test/groovy/test/TestStatement.groovy deleted file mode 100644 index 3a2605c353..0000000000 --- a/instrumentation/jdbc/src/test/groovy/test/TestStatement.groovy +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test - -import java.sql.Connection -import java.sql.ResultSet -import java.sql.SQLException -import java.sql.SQLWarning -import java.sql.Statement - -class TestStatement implements Statement { - final Connection connection - - TestStatement(Connection connection) { - this.connection = connection - } - - @Override - ResultSet executeQuery(String sql) throws SQLException { - return null - } - - @Override - int executeUpdate(String sql) throws SQLException { - return 0 - } - - @Override - void close() throws SQLException { - - } - - @Override - int getMaxFieldSize() throws SQLException { - return 0 - } - - @Override - void setMaxFieldSize(int max) throws SQLException { - - } - - @Override - int getMaxRows() throws SQLException { - return 0 - } - - @Override - void setMaxRows(int max) throws SQLException { - - } - - @Override - void setEscapeProcessing(boolean enable) throws SQLException { - - } - - @Override - int getQueryTimeout() throws SQLException { - return 0 - } - - @Override - void setQueryTimeout(int seconds) throws SQLException { - - } - - @Override - void cancel() throws SQLException { - - } - - @Override - SQLWarning getWarnings() throws SQLException { - return null - } - - @Override - void clearWarnings() throws SQLException { - - } - - @Override - void setCursorName(String name) throws SQLException { - - } - - @Override - boolean execute(String sql) throws SQLException { - return false - } - - @Override - ResultSet getResultSet() throws SQLException { - return null - } - - @Override - int getUpdateCount() throws SQLException { - return 0 - } - - @Override - boolean getMoreResults() throws SQLException { - return false - } - - @Override - void setFetchDirection(int direction) throws SQLException { - - } - - @Override - int getFetchDirection() throws SQLException { - return 0 - } - - @Override - void setFetchSize(int rows) throws SQLException { - - } - - @Override - int getFetchSize() throws SQLException { - return 0 - } - - @Override - int getResultSetConcurrency() throws SQLException { - return 0 - } - - @Override - int getResultSetType() throws SQLException { - return 0 - } - - @Override - void addBatch(String sql) throws SQLException { - - } - - @Override - void clearBatch() throws SQLException { - - } - - @Override - int[] executeBatch() throws SQLException { - return new int[0] - } - - @Override - Connection getConnection() throws SQLException { - return connection - } - - @Override - boolean getMoreResults(int current) throws SQLException { - return false - } - - @Override - ResultSet getGeneratedKeys() throws SQLException { - return null - } - - @Override - int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - return 0 - } - - @Override - int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - return 0 - } - - @Override - int executeUpdate(String sql, String[] columnNames) throws SQLException { - return 0 - } - - @Override - boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - return false - } - - @Override - boolean execute(String sql, int[] columnIndexes) throws SQLException { - return false - } - - @Override - boolean execute(String sql, String[] columnNames) throws SQLException { - return false - } - - @Override - int getResultSetHoldability() throws SQLException { - return 0 - } - - @Override - boolean isClosed() throws SQLException { - return false - } - - @Override - void setPoolable(boolean poolable) throws SQLException { - - } - - @Override - boolean isPoolable() throws SQLException { - return false - } - - @Override - void closeOnCompletion() throws SQLException { - - } - - @Override - boolean isCloseOnCompletion() throws SQLException { - return false - } - - @Override - def T unwrap(Class iface) throws SQLException { - return null - } - - @Override - boolean isWrapperFor(Class iface) throws SQLException { - return false - } -} diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy b/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy index d9434e2f59..82b3cd5eeb 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/test/groovy/JedisClientTest.groovy @@ -5,9 +5,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import redis.clients.jedis.Jedis import redis.embedded.RedisServer import spock.lang.Shared diff --git a/instrumentation/jedis/jedis-1.4/jedis-1.4.gradle b/instrumentation/jedis/jedis-1.4/jedis-1.4.gradle deleted file mode 100644 index be5f3f8245..0000000000 --- a/instrumentation/jedis/jedis-1.4/jedis-1.4.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "redis.clients" - module = "jedis" - versions = "[1.4.0,3.0.0)" - assertInverse = true - } -} - -dependencies { - library group: 'redis.clients', name: 'jedis', version: '1.4.0' - - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' - - // Jedis 3.0 has API changes that prevent instrumentation from applying - latestDepTestLibrary group: 'redis.clients', name: 'jedis', version: '2.+' -} diff --git a/instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java b/instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java deleted file mode 100644 index 9d955305de..0000000000 --- a/instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisClientTracer.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; - -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import io.opentelemetry.javaagent.instrumentation.api.db.RedisCommandNormalizer; -import io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisClientTracer.CommandWithArgs; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.List; -import redis.clients.jedis.Connection; -import redis.clients.jedis.Protocol.Command; - -public class JedisClientTracer extends DatabaseClientTracer { - private static final JedisClientTracer TRACER = new JedisClientTracer(); - - public static JedisClientTracer tracer() { - return TRACER; - } - - private final RedisCommandNormalizer commandNormalizer = - new RedisCommandNormalizer("jedis", "jedis-1.4"); - - @Override - protected String spanName(Connection connection, CommandWithArgs query, String normalizedQuery) { - return query.getStringCommand(); - } - - @Override - protected String normalizeQuery(CommandWithArgs command) { - return commandNormalizer.normalize(command.getStringCommand(), command.getArgs()); - } - - @Override - protected String dbSystem(Connection connection) { - return DbSystem.REDIS; - } - - @Override - protected String dbConnectionString(Connection connection) { - return connection.getHost() + ":" + connection.getPort(); - } - - @Override - protected InetSocketAddress peerAddress(Connection connection) { - return new InetSocketAddress(connection.getHost(), connection.getPort()); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jedis"; - } - - public static final class CommandWithArgs { - private static final byte[][] NO_ARGS = new byte[0][]; - - private final Command command; - private final byte[][] args; - - public CommandWithArgs(Command command, byte[][] args) { - this.command = command; - this.args = args; - } - - public CommandWithArgs(Command command) { - this(command, NO_ARGS); - } - - private String getStringCommand() { - return command.name(); - } - - private List getArgs() { - return Arrays.asList(args); - } - } -} diff --git a/instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java b/instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java deleted file mode 100644 index e7c24a634f..0000000000 --- a/instrumentation/jedis/jedis-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisInstrumentationModule.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; - -import static io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.is; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.jedis.v1_4.JedisClientTracer.CommandWithArgs; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import redis.clients.jedis.Connection; -import redis.clients.jedis.Protocol.Command; - -@AutoService(InstrumentationModule.class) -public class JedisInstrumentationModule extends InstrumentationModule { - - public JedisInstrumentationModule() { - super("jedis", "jedis-1.4"); - } - - @Override - public ElementMatcher.Junction classLoaderMatcher() { - // Avoid matching 3.x - return not(hasClassesNamed("redis.clients.jedis.commands.ProtocolCommand")); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ConnectionInstrumentation()); - } - - public static class ConnectionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("redis.clients.jedis.Connection"); - } - - @Override - public Map, String> transformers() { - // FIXME: This instrumentation only incorporates sending the command, not processing the - // result. - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(named("sendCommand")) - .and(takesArguments(1)) - .and(takesArgument(0, named("redis.clients.jedis.Protocol$Command"))), - JedisInstrumentationModule.class.getName() + "$JedisNoArgsAdvice"); - transformers.put( - isMethod() - .and(named("sendCommand")) - .and(takesArguments(2)) - .and(takesArgument(0, named("redis.clients.jedis.Protocol$Command"))) - .and(takesArgument(1, is(byte[][].class))), - JedisInstrumentationModule.class.getName() + "$JedisArgsAdvice"); - return transformers; - } - } - - public static class JedisNoArgsAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This Connection connection, - @Advice.Argument(0) Command command, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(Connection.class); - if (callDepth > 0) { - return; - } - - span = tracer().startSpan(connection, new CommandWithArgs(command)); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - CallDepthThreadLocalMap.reset(Connection.class); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } - - public static class JedisArgsAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This Connection connection, - @Advice.Argument(0) Command command, - @Advice.Argument(1) byte[][] args, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(Connection.class); - if (callDepth > 0) { - return; - } - - span = tracer().startSpan(connection, new CommandWithArgs(command, args)); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - CallDepthThreadLocalMap.reset(Connection.class); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jedis/jedis-1.4/src/test/groovy/JedisClientTest.groovy b/instrumentation/jedis/jedis-1.4/src/test/groovy/JedisClientTest.groovy deleted file mode 100644 index 82b3cd5eeb..0000000000 --- a/instrumentation/jedis/jedis-1.4/src/test/groovy/JedisClientTest.groovy +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import redis.clients.jedis.Jedis -import redis.embedded.RedisServer -import spock.lang.Shared - -class JedisClientTest extends AgentTestRunner { - - @Shared - int port = PortUtils.randomOpenPort() - - @Shared - RedisServer redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind 127.0.0.1") - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - @Shared - Jedis jedis = new Jedis("localhost", port) - - def setupSpec() { - println "Using redis: $redisServer.args" - redisServer.start() - } - - def cleanupSpec() { - redisServer.stop() -// jedis.close() // not available in the early version we're using. - } - - def setup() { - jedis.flushAll() - TEST_WRITER.clear() - } - - def "set command"() { - when: - jedis.set("foo", "bar") - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - } - } - - def "get command"() { - when: - jedis.set("foo", "bar") - def value = jedis.get("foo") - - then: - value == "bar" - - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - trace(1, 1) { - span(0) { - name "GET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "GET foo" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - } - } - - def "command with no arguments"() { - when: - jedis.set("foo", "bar") - def value = jedis.randomKey() - - then: - value == "foo" - - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - trace(1, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "RANDOMKEY" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - } - } -} diff --git a/instrumentation/jedis/jedis-3.0/javaagent/src/test/groovy/Jedis30ClientTest.groovy b/instrumentation/jedis/jedis-3.0/javaagent/src/test/groovy/Jedis30ClientTest.groovy index 61139418f8..732668b979 100644 --- a/instrumentation/jedis/jedis-3.0/javaagent/src/test/groovy/Jedis30ClientTest.groovy +++ b/instrumentation/jedis/jedis-3.0/javaagent/src/test/groovy/Jedis30ClientTest.groovy @@ -5,9 +5,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import redis.clients.jedis.Jedis import redis.embedded.RedisServer import spock.lang.Shared diff --git a/instrumentation/jedis/jedis-3.0/jedis-3.0.gradle b/instrumentation/jedis/jedis-3.0/jedis-3.0.gradle deleted file mode 100644 index faa20ec18d..0000000000 --- a/instrumentation/jedis/jedis-3.0/jedis-3.0.gradle +++ /dev/null @@ -1,26 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - fail { - group = "redis.clients" - module = "jedis" - versions = "[,3.0.0)" - } - - pass { - group = "redis.clients" - module = "jedis" - versions = "[3.0.0,)" - } -} - -dependencies { - library group: 'redis.clients', name: 'jedis', version: '3.0.0' - - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' - // ensures jedis-1.4 instrumentation does not load with jedis 3.0+ by failing - // the tests in the event it does. The tests will end up with double spans - testImplementation project(':instrumentation:jedis:jedis-1.4') - - testLibrary group: 'redis.clients', name: 'jedis', version: '3.+' -} diff --git a/instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisClientTracer.java b/instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisClientTracer.java deleted file mode 100644 index a42cc116c7..0000000000 --- a/instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisClientTracer.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jedis.v3_0; - -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import io.opentelemetry.javaagent.instrumentation.api.db.RedisCommandNormalizer; -import io.opentelemetry.javaagent.instrumentation.jedis.v3_0.JedisClientTracer.CommandWithArgs; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; -import redis.clients.jedis.Connection; -import redis.clients.jedis.Protocol; -import redis.clients.jedis.commands.ProtocolCommand; - -public class JedisClientTracer extends DatabaseClientTracer { - private static final JedisClientTracer TRACER = new JedisClientTracer(); - - public static JedisClientTracer tracer() { - return TRACER; - } - - private final RedisCommandNormalizer commandNormalizer = - new RedisCommandNormalizer("jedis", "jedis-3.0"); - - @Override - protected String spanName(Connection connection, CommandWithArgs query, String normalizedQuery) { - return query.getStringCommand(); - } - - @Override - protected String normalizeQuery(CommandWithArgs command) { - return commandNormalizer.normalize(command.getStringCommand(), command.getArgs()); - } - - @Override - protected String dbSystem(Connection connection) { - return DbSystem.REDIS; - } - - @Override - protected String dbConnectionString(Connection connection) { - return connection.getHost() + ":" + connection.getPort(); - } - - @Override - protected InetSocketAddress peerAddress(Connection connection) { - return new InetSocketAddress(connection.getHost(), connection.getPort()); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jedis"; - } - - public static final class CommandWithArgs { - private final ProtocolCommand command; - private final byte[][] args; - - public CommandWithArgs(ProtocolCommand command, byte[][] args) { - this.command = command; - this.args = args; - } - - private String getStringCommand() { - if (command instanceof Protocol.Command) { - return ((Protocol.Command) command).name(); - } else { - // Protocol.Command is the only implementation in the Jedis lib as of 3.1 but this will save - // us if that changes - return new String(command.getRaw(), StandardCharsets.UTF_8); - } - } - - private List getArgs() { - return Arrays.asList(args); - } - } -} diff --git a/instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisInstrumentationModule.java b/instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisInstrumentationModule.java deleted file mode 100644 index 8dc4f84789..0000000000 --- a/instrumentation/jedis/jedis-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisInstrumentationModule.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jedis.v3_0; - -import static io.opentelemetry.javaagent.instrumentation.jedis.v3_0.JedisClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.is; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.jedis.v3_0.JedisClientTracer.CommandWithArgs; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import redis.clients.jedis.Connection; -import redis.clients.jedis.commands.ProtocolCommand; - -@AutoService(InstrumentationModule.class) -public class JedisInstrumentationModule extends InstrumentationModule { - - public JedisInstrumentationModule() { - super("jedis", "jedis-3.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ConnectionInstrumentation()); - } - - public static class ConnectionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("redis.clients.jedis.Connection"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("sendCommand")) - .and(takesArguments(2)) - .and(takesArgument(0, named("redis.clients.jedis.commands.ProtocolCommand"))) - .and(takesArgument(1, is(byte[][].class))), - JedisInstrumentationModule.class.getName() + "$JedisAdvice"); - // FIXME: This instrumentation only incorporates sending the command, not processing the - // result. - } - } - - public static class JedisAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This Connection connection, - @Advice.Argument(0) ProtocolCommand command, - @Advice.Argument(1) byte[][] args, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(connection, new CommandWithArgs(command, args)); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jedis/jedis-3.0/src/test/groovy/Jedis30ClientTest.groovy b/instrumentation/jedis/jedis-3.0/src/test/groovy/Jedis30ClientTest.groovy deleted file mode 100644 index 732668b979..0000000000 --- a/instrumentation/jedis/jedis-3.0/src/test/groovy/Jedis30ClientTest.groovy +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import redis.clients.jedis.Jedis -import redis.embedded.RedisServer -import spock.lang.Shared - -class Jedis30ClientTest extends AgentTestRunner { - - @Shared - int port = PortUtils.randomOpenPort() - - @Shared - RedisServer redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind 127.0.0.1") - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - @Shared - Jedis jedis = new Jedis("localhost", port) - - def setupSpec() { - println "Using redis: $redisServer.args" - redisServer.start() - } - - def cleanupSpec() { - redisServer.stop() - jedis.close() - } - - def setup() { - jedis.flushAll() - TEST_WRITER.clear() - } - - def "set command"() { - when: - jedis.set("foo", "bar") - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - } - } - - def "get command"() { - when: - jedis.set("foo", "bar") - def value = jedis.get("foo") - - then: - value == "bar" - - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - trace(1, 1) { - span(0) { - name "GET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "GET foo" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - } - } - - def "command with no arguments"() { - when: - jedis.set("foo", "bar") - def value = jedis.randomKey() - - then: - value == "foo" - - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - trace(1, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.DB_STATEMENT.key" "RANDOMKEY" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_PORT.key" port - } - } - } - } - } -} diff --git a/instrumentation/jetty-8.0/jetty-8.0.gradle b/instrumentation/jetty-8.0/jetty-8.0.gradle deleted file mode 100644 index f409812577..0000000000 --- a/instrumentation/jetty-8.0/jetty-8.0.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.eclipse.jetty" - module = 'jetty-server' - versions = "[8.0.0.v20110901,)" - assertInverse = true - } -} - -dependencies { - library group: 'org.eclipse.jetty', name: 'jetty-server', version: '8.0.0.v20110901' - implementation project(':instrumentation:servlet:servlet-3.0:javaagent') - - // Don't want to conflict with jetty from the test server. - testImplementation(project(':testing-common')) { - exclude group: 'org.eclipse.jetty', module: 'jetty-server' - } - - testLibrary group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '8.0.0.v20110901' - testLibrary group: 'org.eclipse.jetty', name: 'jetty-continuation', version: '8.0.0.v20110901' - - // Jetty 10 seems to refuse to run on java8. - // TODO: we need to setup separate test for Jetty 10 when that is released. - latestDepTestLibrary group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.+' - latestDepTestLibrary group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.+' - latestDepTestLibrary group: 'org.eclipse.jetty', name: 'jetty-continuation', version: '9.+' -} diff --git a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyHandlerAdvice.java b/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyHandlerAdvice.java deleted file mode 100644 index 2dc4b763a0..0000000000 --- a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyHandlerAdvice.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jetty; - -import static io.opentelemetry.javaagent.instrumentation.jetty.JettyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.servlet.v3_0.TagSettingAsyncListener; -import java.lang.reflect.Method; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import net.bytebuddy.asm.Advice; - -public class JettyHandlerAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Origin Method method, - @Advice.This Object source, - @Advice.Argument(value = 2, readOnly = false) HttpServletRequest request, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - Context attachedContext = tracer().getServerContext(request); - if (attachedContext != null) { - // We are inside nested handler, don't create new span - return; - } - - Context ctx = tracer().startSpan(request, request, method); - span = Java8BytecodeBridge.spanFromContext(ctx); - scope = tracer().startScope(span, request); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Argument(2) HttpServletRequest request, - @Advice.Argument(3) HttpServletResponse response, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - - if (span == null) { - // an existing span was found - return; - } - - tracer().setPrincipal(span, request); - - if (throwable != null) { - tracer().endExceptionally(span, throwable, response); - return; - } - - AtomicBoolean responseHandled = new AtomicBoolean(false); - - // In case of async servlets wait for the actual response to be ready - if (request.isAsyncStarted()) { - try { - request.getAsyncContext().addListener(new TagSettingAsyncListener(responseHandled, span)); - } catch (IllegalStateException e) { - // org.eclipse.jetty.server.Request may throw an exception here if request became - // finished after check above. We just ignore that exception and move on. - } - } - - // Check again in case the request finished before adding the listener. - if (!request.isAsyncStarted() && responseHandled.compareAndSet(false, true)) { - tracer().end(span, response); - } - } -} diff --git a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyHttpServerTracer.java b/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyHttpServerTracer.java deleted file mode 100644 index 3eac1f6e2a..0000000000 --- a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyHttpServerTracer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jetty; - -import io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3HttpServerTracer; - -public class JettyHttpServerTracer extends Servlet3HttpServerTracer { - private static final JettyHttpServerTracer TRACER = new JettyHttpServerTracer(); - - public static JettyHttpServerTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jetty"; - } -} diff --git a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyInstrumentationModule.java b/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyInstrumentationModule.java deleted file mode 100644 index 5142b5de86..0000000000 --- a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/JettyInstrumentationModule.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jetty; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class JettyInstrumentationModule extends InstrumentationModule { - - public JettyInstrumentationModule() { - super("jetty", "jetty-8.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HandlerInstrumentation()); - } - - public static class HandlerInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.eclipse.jetty.server.Handler"); - } - - @Override - public ElementMatcher typeMatcher() { - // skipping built-in handlers, so that for servlets there will be no span started by jetty. - // this is so that the servlet instrumentation will capture contextPath and servletPath - // normally, which the jetty instrumentation does not capture since jetty doesn't populate - // contextPath and servletPath until right before calling the servlet - // (another option is to instrument ServletHolder.handle() to capture those fields) - return not(named("org.eclipse.jetty.server.handler.HandlerWrapper")) - .and(not(named("org.eclipse.jetty.server.handler.ScopedHandler"))) - .and(not(named("org.eclipse.jetty.server.handler.ContextHandler"))) - .and(not(named("org.eclipse.jetty.servlet.ServletHandler"))) - .and(implementsInterface(named("org.eclipse.jetty.server.Handler"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("handle") - // need to capture doHandle() for handlers that extend built-in handlers excluded - // above - .or(named("doHandle")) - .and(takesArgument(0, named("java.lang.String"))) - .and(takesArgument(1, named("org.eclipse.jetty.server.Request"))) - .and(takesArgument(2, named("javax.servlet.http.HttpServletRequest"))) - .and(takesArgument(3, named("javax.servlet.http.HttpServletResponse"))) - .and(isPublic()), - JettyHandlerAdvice.class.getName()); - } - } -} diff --git a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/package-info.java b/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/package-info.java deleted file mode 100644 index 748bfce2ea..0000000000 --- a/instrumentation/jetty-8.0/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/package-info.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * This module provides support for creating server spans for Jetty Handlers. - * - *

It is possible to write web application running on Eclipse Jetty without actually writing any servlets. - * Instead one can use Jetty - * Handlers. - * - *

As instrumentation points differ between servlet instrumentations and this one, this module - * has its own {@code JettyHandlerInstrumentation} and {@code JettyHandlerAdvice}. But this is the - * only difference between two instrumentations, thus {@link - * io.opentelemetry.javaagent.instrumentation.jetty.JettyHttpServerTracer} is a very thin subclass - * of {@link io.opentelemetry.javaagent.instrumentation.servlet.v3_0.Servlet3HttpServerTracer}. - */ -package io.opentelemetry.javaagent.instrumentation.jetty; diff --git a/instrumentation/jetty-8.0/src/test/groovy/JettyContinuationHandlerTest.groovy b/instrumentation/jetty-8.0/src/test/groovy/JettyContinuationHandlerTest.groovy deleted file mode 100644 index 46b22dc17c..0000000000 --- a/instrumentation/jetty-8.0/src/test/groovy/JettyContinuationHandlerTest.groovy +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import javax.servlet.ServletException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse -import org.eclipse.jetty.continuation.Continuation -import org.eclipse.jetty.continuation.ContinuationSupport -import org.eclipse.jetty.server.Request -import org.eclipse.jetty.server.handler.AbstractHandler - -// FIXME: We don't currently handle jetty continuations properly (at all). -abstract class JettyContinuationHandlerTest extends JettyHandlerTest { - - @Override - AbstractHandler handler() { - ContinuationTestHandler.INSTANCE - } - - static class ContinuationTestHandler extends AbstractHandler { - static final ContinuationTestHandler INSTANCE = new ContinuationTestHandler() - final ExecutorService executorService = Executors.newSingleThreadExecutor() - - @Override - void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - final Continuation continuation = ContinuationSupport.getContinuation(request) - if (continuation.initial) { - continuation.suspend() - executorService.execute { - continuation.resume() - } - } else { - handleRequest(baseRequest, response) - } - baseRequest.handled = true - } - } - -// // This server seems to generate a TEST_SPAN twice... once for the initial request, and once for the continuation. -// void cleanAndAssertTraces( -// final int size, -// @ClosureParams(value = SimpleType, options = "io.opentelemetry.instrumentation.test.asserts.ListWriterAssert") -// @DelegatesTo(value = ListWriterAssert, strategy = Closure.DELEGATE_FIRST) -// final Closure spec) { -// -// // If this is failing, make sure HttpServerTestAdvice is applied correctly. -// TEST_WRITER.waitForTraces(size * 3) -// // TEST_WRITER is a CopyOnWriteArrayList, which doesn't support remove() -// def toRemove = TEST_WRITER.findAll { -// it.size() == 1 && it.get(0).name == "TEST_SPAN" -// } -// toRemove.each { -// assertTrace(it, 1) { -// basicSpan(it, 0, "TEST_SPAN") -// } -// } -// assert toRemove.size() == size * 2 -// TEST_WRITER.removeAll(toRemove) -// -// assertTraces(size, spec) -// } -} diff --git a/instrumentation/jetty-8.0/src/test/groovy/JettyHandlerTest.groovy b/instrumentation/jetty-8.0/src/test/groovy/JettyHandlerTest.groovy deleted file mode 100644 index 9013d465e3..0000000000 --- a/instrumentation/jetty-8.0/src/test/groovy/JettyHandlerTest.groovy +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import javax.servlet.DispatcherType -import javax.servlet.ServletException -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse -import org.eclipse.jetty.server.Request -import org.eclipse.jetty.server.Response -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.server.handler.AbstractHandler -import org.eclipse.jetty.server.handler.ErrorHandler -import spock.lang.Shared - -class JettyHandlerTest extends HttpServerTest { - - @Shared - ErrorHandler errorHandler = new ErrorHandler() { - @Override - protected void handleErrorPage(HttpServletRequest request, Writer writer, int code, String message) throws IOException { - Throwable th = (Throwable) request.getAttribute("javax.servlet.error.exception") - message = th ? th.message : message - if (message) { - writer.write(message) - } - } - } - - @Shared - TestHandler testHandler = new TestHandler() - - @Override - Server startServer(int port) { - def server = new Server(port) - server.setHandler(handler()) - server.addBean(errorHandler) - server.start() - return server - } - - AbstractHandler handler() { - testHandler - } - - @Override - void stopServer(Server server) { - server.stop() - } - - @Override - boolean testExceptionBody() { - false - } - - static void handleRequest(Request request, HttpServletResponse response) { - ServerEndpoint endpoint = ServerEndpoint.forPath(request.requestURI) - controller(endpoint) { - response.contentType = "text/plain" - switch (endpoint) { - case SUCCESS: - response.status = endpoint.status - response.writer.print(endpoint.body) - break - case QUERY_PARAM: - response.status = endpoint.status - response.writer.print(request.queryString) - break - case REDIRECT: - response.sendRedirect(endpoint.body) - break - case ERROR: - response.sendError(endpoint.status, endpoint.body) - break - case EXCEPTION: - throw new Exception(endpoint.body) - default: - response.status = NOT_FOUND.status - response.writer.print(NOT_FOUND.body) - break - } - } - } - - static class TestHandler extends AbstractHandler { - @Override - void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - //This line here is to verify that we don't break Jetty if it wants to cast to implementation class - //See https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1096 - Response jettyResponse = response as Response - if (baseRequest.dispatcherType != DispatcherType.ERROR) { - handleRequest(baseRequest, jettyResponse) - baseRequest.handled = true - } else { - errorHandler.handle(target, baseRequest, response, response) - } - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - "TestHandler.handle" - } -} diff --git a/instrumentation/jms-1.1/jms-1.1.gradle b/instrumentation/jms-1.1/jms-1.1.gradle deleted file mode 100644 index 7dc969674c..0000000000 --- a/instrumentation/jms-1.1/jms-1.1.gradle +++ /dev/null @@ -1,42 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply plugin: 'org.unbroken-dome.test-sets' - -muzzle { - pass { - group = "javax.jms" - module = "jms-api" - versions = "(,)" - } - pass { - group = "javax.jms" - module = "javax.jms-api" - versions = "(,)" - } -} - -testSets { - jms2Test { - filter { - // this is needed because "test.dependsOn jms2Test", and so without this, - // running a single test in the default test set will fail - setFailOnNoMatchingTests(false) - } - } -} - -// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/919 -jms2Test.forkEvery 1 -test.dependsOn jms2Test - -dependencies { - compileOnly group: 'javax.jms', name: 'jms-api', version: '1.1-rev-1' - - testImplementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' - testImplementation("org.springframework.boot:spring-boot-starter-activemq:${versions.springboot}") - testImplementation(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: versions.springboot) { - exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' - } - - jms2TestImplementation group: 'org.hornetq', name: 'hornetq-jms-client', version: '2.4.7.Final' - jms2TestImplementation group: 'org.hornetq', name: 'hornetq-jms-server', version: '2.4.7.Final' -} diff --git a/instrumentation/jms-1.1/src/jms2Test/groovy/Jms2Test.groovy b/instrumentation/jms-1.1/src/jms2Test/groovy/Jms2Test.groovy deleted file mode 100644 index 9a2914f155..0000000000 --- a/instrumentation/jms-1.1/src/jms2Test/groovy/Jms2Test.groovy +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER - -import com.google.common.io.Files -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.javaagent.instrumentation.jms.JmsTracer -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.concurrent.CountDownLatch -import java.util.concurrent.atomic.AtomicReference -import javax.jms.Message -import javax.jms.MessageListener -import javax.jms.Session -import javax.jms.TextMessage -import org.hornetq.api.core.TransportConfiguration -import org.hornetq.api.core.client.HornetQClient -import org.hornetq.api.jms.HornetQJMSClient -import org.hornetq.api.jms.JMSFactoryType -import org.hornetq.core.config.Configuration -import org.hornetq.core.config.CoreQueueConfiguration -import org.hornetq.core.config.impl.ConfigurationImpl -import org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory -import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory -import org.hornetq.core.server.HornetQServer -import org.hornetq.core.server.HornetQServers -import org.hornetq.jms.client.HornetQTextMessage -import spock.lang.Shared - -class Jms2Test extends AgentTestRunner { - @Shared - HornetQServer server - @Shared - String messageText = "a message" - @Shared - Session session - - HornetQTextMessage message = session.createTextMessage(messageText) - - def setupSpec() { - def tempDir = Files.createTempDir() - tempDir.deleteOnExit() - - Configuration config = new ConfigurationImpl() - config.bindingsDirectory = tempDir.path - config.journalDirectory = tempDir.path - config.createBindingsDir = false - config.createJournalDir = false - config.securityEnabled = false - config.persistenceEnabled = false - config.setQueueConfigurations([new CoreQueueConfiguration("someQueue", "someQueue", null, true)]) - config.setAcceptorConfigurations([new TransportConfiguration(InVMAcceptorFactory.name)].toSet()) - - server = HornetQServers.newHornetQServer(config) - server.start() - - def serverLocator = HornetQClient.createServerLocatorWithoutHA(new TransportConfiguration(InVMConnectorFactory.name)) - def sf = serverLocator.createSessionFactory() - def clientSession = sf.createSession(false, false, false) - clientSession.createQueue("jms.queue.someQueue", "jms.queue.someQueue", true) - clientSession.createQueue("jms.topic.someTopic", "jms.topic.someTopic", true) - clientSession.close() - sf.close() - serverLocator.close() - - def connectionFactory = HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, - new TransportConfiguration(InVMConnectorFactory.name)) - - def connection = connectionFactory.createConnection() - connection.start() - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE) - session.run() - } - - def cleanupSpec() { - server.stop() - } - - def "sending a message to #destinationName #destinationType generates spans"() { - setup: - def producer = session.createProducer(destination) - def consumer = session.createConsumer(destination) - - producer.send(message) - - TextMessage receivedMessage = consumer.receive() - String messageId = receivedMessage.getJMSMessageID() - - expect: - receivedMessage.text == messageText - assertTraces(2) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - consumerSpan(it, 0, destinationType, destinationName, messageId, null, "receive") - } - } - - cleanup: - producer.close() - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - session.createTemporaryQueue() | "queue" | JmsTracer.TEMP_DESTINATION_NAME - session.createTemporaryTopic() | "topic" | JmsTracer.TEMP_DESTINATION_NAME - } - - def "sending to a MessageListener on #destinationName #destinationType generates a span"() { - setup: - def lock = new CountDownLatch(1) - def messageRef = new AtomicReference() - def producer = session.createProducer(destination) - def consumer = session.createConsumer(destination) - consumer.setMessageListener new MessageListener() { - @Override - void onMessage(Message message) { - lock.await() // ensure the producer trace is reported first. - messageRef.set(message) - } - } - - producer.send(message) - lock.countDown() - - expect: - assertTraces(1) { - trace(0, 2) { - producerSpan(it, 0, destinationType, destinationName) - consumerSpan(it, 1, destinationType, destinationName, messageRef.get().getJMSMessageID(), span(0), "process") - } - } - // This check needs to go after all traces have been accounted for - messageRef.get().text == messageText - - cleanup: - producer.close() - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - session.createTemporaryQueue() | "queue" | JmsTracer.TEMP_DESTINATION_NAME - session.createTemporaryTopic() | "topic" | JmsTracer.TEMP_DESTINATION_NAME - } - - def "failing to receive message with receiveNoWait on #destinationName #destinationType works"() { - setup: - def consumer = session.createConsumer(destination) - - // Receive with timeout - TextMessage receivedMessage = consumer.receiveNoWait() - - expect: - receivedMessage == null - assertTraces(1) { - trace(0, 1) { // Consumer trace - span(0) { - hasNoParent() - name destinationName + " receive" - kind CONSUMER - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" - } - } - } - } - - cleanup: - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - } - - def "failing to receive message with wait(timeout) on #destinationName #destinationType works"() { - setup: - def consumer = session.createConsumer(destination) - - // Receive with timeout - TextMessage receivedMessage = consumer.receive(100) - - expect: - receivedMessage == null - assertTraces(1) { - trace(0, 1) { // Consumer trace - span(0) { - hasNoParent() - name destinationName + " receive" - kind CONSUMER - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" - - } - } - } - } - - cleanup: - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - } - - static producerSpan(TraceAssert trace, int index, String destinationType, String destinationName) { - trace.span(index) { - name destinationName + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - if (destinationName == JmsTracer.TEMP_DESTINATION_NAME) { - "${SemanticAttributes.MESSAGING_TEMP_DESTINATION.key}" true - } - } - } - } - - // passing messageId = null will verify message.id is not captured, - // passing messageId = "" will verify message.id is captured (but won't verify anything about the value), - // any other value for messageId will verify that message.id is captured and has that same value - static consumerSpan(TraceAssert trace, int index, String destinationType, String destinationName, String messageId, Object parentOrLinkedSpan, String operation) { - trace.span(index) { - name destinationName + " " + operation - kind CONSUMER - if (parentOrLinkedSpan != null) { - childOf((SpanData) parentOrLinkedSpan) - } else { - hasNoParent() - } - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_OPERATION.key}" operation - if (messageId != null) { - //In some tests we don't know exact messageId, so we pass "" and verify just the existence of the attribute - "${SemanticAttributes.MESSAGING_MESSAGE_ID.key}" { it == messageId || messageId == "" } - } - if (destinationName == JmsTracer.TEMP_DESTINATION_NAME) { - "${SemanticAttributes.MESSAGING_TEMP_DESTINATION.key}" true - } - } - } - } -} diff --git a/instrumentation/jms-1.1/src/jms2Test/groovy/SpringListenerJms2Test.groovy b/instrumentation/jms-1.1/src/jms2Test/groovy/SpringListenerJms2Test.groovy deleted file mode 100644 index b9a32cab80..0000000000 --- a/instrumentation/jms-1.1/src/jms2Test/groovy/SpringListenerJms2Test.groovy +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Jms2Test.consumerSpan -import static Jms2Test.producerSpan - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import javax.jms.ConnectionFactory -import listener.Config -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.jms.core.JmsTemplate - -class SpringListenerJms2Test extends AgentTestRunner { - def "receiving message in spring listener generates spans"() { - setup: - def context = new AnnotationConfigApplicationContext(Config) - def factory = context.getBean(ConnectionFactory) - def template = new JmsTemplate(factory) - template.convertAndSend("SpringListenerJms2", "a message") - - expect: - assertTraces(2) { - trace(0, 2) { - producerSpan(it, 0, "queue", "SpringListenerJms2") - consumerSpan(it, 1, "queue", "SpringListenerJms2", "", span(0), "process") - } - trace(1, 1) { - consumerSpan(it, 0, "queue", "SpringListenerJms2", "", null, "receive") - } - } - - cleanup: - context.close() - } -} diff --git a/instrumentation/jms-1.1/src/jms2Test/groovy/SpringTemplateJms2Test.groovy b/instrumentation/jms-1.1/src/jms2Test/groovy/SpringTemplateJms2Test.groovy deleted file mode 100644 index f6c41a4aa8..0000000000 --- a/instrumentation/jms-1.1/src/jms2Test/groovy/SpringTemplateJms2Test.groovy +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Jms2Test.consumerSpan -import static Jms2Test.producerSpan - -import com.google.common.io.Files -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicReference -import javax.jms.Session -import javax.jms.TextMessage -import org.hornetq.api.core.TransportConfiguration -import org.hornetq.api.core.client.HornetQClient -import org.hornetq.api.jms.HornetQJMSClient -import org.hornetq.api.jms.JMSFactoryType -import org.hornetq.core.config.Configuration -import org.hornetq.core.config.CoreQueueConfiguration -import org.hornetq.core.config.impl.ConfigurationImpl -import org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory -import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory -import org.hornetq.core.server.HornetQServer -import org.hornetq.core.server.HornetQServers -import org.springframework.jms.core.JmsTemplate -import spock.lang.Shared - -class SpringTemplateJms2Test extends AgentTestRunner { - @Shared - HornetQServer server - @Shared - String messageText = "a message" - @Shared - JmsTemplate template - @Shared - Session session - - def setupSpec() { - def tempDir = Files.createTempDir() - tempDir.deleteOnExit() - - Configuration config = new ConfigurationImpl() - config.bindingsDirectory = tempDir.path - config.journalDirectory = tempDir.path - config.createBindingsDir = false - config.createJournalDir = false - config.securityEnabled = false - config.persistenceEnabled = false - config.setQueueConfigurations([new CoreQueueConfiguration("someQueue", "someQueue", null, true)]) - config.setAcceptorConfigurations([new TransportConfiguration(InVMAcceptorFactory.name)].toSet()) - - server = HornetQServers.newHornetQServer(config) - server.start() - - def serverLocator = HornetQClient.createServerLocatorWithoutHA(new TransportConfiguration(InVMConnectorFactory.name)) - def sf = serverLocator.createSessionFactory() - def clientSession = sf.createSession(false, false, false) - clientSession.createQueue("jms.queue.SpringTemplateJms2", "jms.queue.SpringTemplateJms2", true) - clientSession.close() - sf.close() - serverLocator.close() - - def connectionFactory = HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, - new TransportConfiguration(InVMConnectorFactory.name)) - - def connection = connectionFactory.createConnection() - connection.start() - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE) - session.run() - - template = new JmsTemplate(connectionFactory) - template.receiveTimeout = TimeUnit.SECONDS.toMillis(10) - } - - def cleanupSpec() { - server.stop() - } - - def "sending a message to #destinationName generates spans"() { - setup: - template.convertAndSend(destination, messageText) - TextMessage receivedMessage = template.receive(destination) - - expect: - receivedMessage.text == messageText - assertTraces(2) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - consumerSpan(it, 0, destinationType, destinationName, receivedMessage.getJMSMessageID(), null, "receive") - } - } - - where: - destination | destinationType | destinationName - session.createQueue("SpringTemplateJms2") | "queue" | "SpringTemplateJms2" - } - - def "send and receive message generates spans"() { - setup: - AtomicReference msgId = new AtomicReference<>() - Thread.start { - TextMessage msg = template.receive(destination) - assert msg.text == messageText - msgId.set(msg.getJMSMessageID()) - - // There's a chance this might be reported last, messing up the assertion. - template.send(msg.getJMSReplyTo()) { - session -> template.getMessageConverter().toMessage("responded!", session) - } - } - TextMessage receivedMessage = template.sendAndReceive(destination) { - session -> template.getMessageConverter().toMessage(messageText, session) - } - - expect: - receivedMessage.text == "responded!" - assertTraces(4) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - consumerSpan(it, 0, destinationType, destinationName, msgId.get(), null, "receive") - } - trace(2, 1) { - producerSpan(it, 0, "queue", "(temporary)") - } - trace(3, 1) { - consumerSpan(it, 0, "queue", "(temporary)", receivedMessage.getJMSMessageID(), null, "receive") - } - } - - where: - destination | destinationType | destinationName - session.createQueue("SpringTemplateJms2") | "queue" | "SpringTemplateJms2" - } -} diff --git a/instrumentation/jms-1.1/src/jms2Test/groovy/listener/Config.groovy b/instrumentation/jms-1.1/src/jms2Test/groovy/listener/Config.groovy deleted file mode 100644 index 1f4f95ede3..0000000000 --- a/instrumentation/jms-1.1/src/jms2Test/groovy/listener/Config.groovy +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package listener - -import com.google.common.io.Files -import javax.annotation.PreDestroy -import javax.jms.ConnectionFactory -import org.hornetq.api.core.TransportConfiguration -import org.hornetq.api.core.client.HornetQClient -import org.hornetq.api.jms.HornetQJMSClient -import org.hornetq.api.jms.JMSFactoryType -import org.hornetq.core.config.CoreQueueConfiguration -import org.hornetq.core.config.impl.ConfigurationImpl -import org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory -import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory -import org.hornetq.core.server.HornetQServer -import org.hornetq.core.server.HornetQServers -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration -import org.springframework.jms.annotation.EnableJms -import org.springframework.jms.config.DefaultJmsListenerContainerFactory -import org.springframework.jms.config.JmsListenerContainerFactory - -@Configuration -@ComponentScan -@EnableJms -class Config { - - private HornetQServer server - - @Bean - ConnectionFactory connectionFactory() { - def tempDir = Files.createTempDir() - tempDir.deleteOnExit() - - org.hornetq.core.config.Configuration config = new ConfigurationImpl() - config.bindingsDirectory = tempDir.path - config.journalDirectory = tempDir.path - config.createBindingsDir = false - config.createJournalDir = false - config.securityEnabled = false - config.persistenceEnabled = false - config.setQueueConfigurations([new CoreQueueConfiguration("someQueue", "someQueue", null, true)]) - config.setAcceptorConfigurations([new TransportConfiguration(InVMAcceptorFactory.name)].toSet()) - - server = HornetQServers.newHornetQServer(config) - server.start() - - def serverLocator = HornetQClient.createServerLocatorWithoutHA(new TransportConfiguration(InVMConnectorFactory.name)) - def sf = serverLocator.createSessionFactory() - def clientSession = sf.createSession(false, false, false) - clientSession.createQueue("jms.queue.SpringListenerJms2", "jms.queue.SpringListenerJms2", true) - clientSession.close() - sf.close() - serverLocator.close() - - return HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, - new TransportConfiguration(InVMConnectorFactory.name)) - } - - @Bean - JmsListenerContainerFactory containerFactory(ConnectionFactory connectionFactory) { - DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory() - factory.setConnectionFactory(connectionFactory) - return factory - } - - @PreDestroy - void destroy() { - server.stop() - } -} diff --git a/instrumentation/jms-1.1/src/jms2Test/groovy/listener/TestListener.groovy b/instrumentation/jms-1.1/src/jms2Test/groovy/listener/TestListener.groovy deleted file mode 100644 index 229dc0b907..0000000000 --- a/instrumentation/jms-1.1/src/jms2Test/groovy/listener/TestListener.groovy +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package listener - -import org.springframework.jms.annotation.JmsListener -import org.springframework.stereotype.Component - -@Component -class TestListener { - - @JmsListener(destination = "SpringListenerJms2", containerFactory = "containerFactory") - void receiveMessage(String message) { - println "received: " + message - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java deleted file mode 100644 index 3fd3adfd04..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class JmsInstrumentationModule extends InstrumentationModule { - public JmsInstrumentationModule() { - super("jms", "jms-1.1"); - } - - @Override - public List typeInstrumentations() { - return asList( - new JmsMessageConsumerInstrumentation(), - new JmsMessageListenerInstrumentation(), - new JmsMessageProducerInstrumentation(), - new JmsSessionInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap("javax.jms.MessageConsumer", MessageDestination.class.getName()); - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageConsumerInstrumentation.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageConsumerInstrumentation.java deleted file mode 100644 index 40ce3b274a..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageConsumerInstrumentation.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import static io.opentelemetry.javaagent.instrumentation.jms.JmsTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JmsMessageConsumerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.jms.MessageConsumer"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.jms.MessageConsumer")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("receive").and(takesArguments(0).or(takesArguments(1))).and(isPublic()), - JmsMessageConsumerInstrumentation.class.getName() + "$ConsumerAdvice"); - transformers.put( - named("receiveNoWait").and(takesArguments(0)).and(isPublic()), - JmsMessageConsumerInstrumentation.class.getName() + "$ConsumerAdvice"); - return transformers; - } - - public static class ConsumerAdvice { - - @Advice.OnMethodEnter - public static long onEnter() { - return System.currentTimeMillis(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.This MessageConsumer consumer, - @Advice.Enter long startTime, - @Advice.Return Message message, - @Advice.Thrown Throwable throwable) { - MessageDestination destination; - if (message == null) { - destination = - InstrumentationContext.get(MessageConsumer.class, MessageDestination.class) - .get(consumer); - if (destination == null) { - destination = MessageDestination.UNKNOWN; - } - } else { - destination = tracer().extractDestination(message, null); - } - - Span span = tracer().startConsumerSpan(destination, "receive", message, startTime); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageListenerInstrumentation.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageListenerInstrumentation.java deleted file mode 100644 index 4504785eb2..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageListenerInstrumentation.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import static io.opentelemetry.javaagent.instrumentation.jms.JmsTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import javax.jms.Message; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JmsMessageListenerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.jms.MessageListener"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.jms.MessageListener")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("onMessage").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()), - JmsMessageListenerInstrumentation.class.getName() + "$MessageListenerAdvice"); - } - - public static class MessageListenerAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Message message, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - MessageDestination destination = tracer().extractDestination(message, null); - span = - tracer().startConsumerSpan(destination, "process", message, System.currentTimeMillis()); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageProducerInstrumentation.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageProducerInstrumentation.java deleted file mode 100644 index 8e772c435c..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageProducerInstrumentation.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import static io.opentelemetry.javaagent.instrumentation.jms.JmsTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageProducer; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JmsMessageProducerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.jms.MessageProducer"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.jms.MessageProducer")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - named("send").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()), - JmsMessageProducerInstrumentation.class.getName() + "$ProducerAdvice"); - transformers.put( - named("send") - .and(takesArgument(0, named("javax.jms.Destination"))) - .and(takesArgument(1, named("javax.jms.Message"))) - .and(isPublic()), - JmsMessageProducerInstrumentation.class.getName() + "$ProducerWithDestinationAdvice"); - return transformers; - } - - public static class ProducerAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Message message, - @Advice.This MessageProducer producer, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(MessageProducer.class); - if (callDepth > 0) { - return; - } - - Destination defaultDestination; - try { - defaultDestination = producer.getDestination(); - } catch (JMSException e) { - defaultDestination = null; - } - - MessageDestination messageDestination = - tracer().extractDestination(message, defaultDestination); - span = tracer().startProducerSpan(messageDestination, message); - scope = tracer().startProducerScope(span, message); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - if (scope == null) { - return; - } - scope.close(); - CallDepthThreadLocalMap.reset(MessageProducer.class); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } - - public static class ProducerWithDestinationAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Destination destination, - @Advice.Argument(1) Message message, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(MessageProducer.class); - if (callDepth > 0) { - return; - } - - MessageDestination messageDestination = tracer().extractDestination(message, destination); - span = tracer().startProducerSpan(messageDestination, message); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - if (scope == null) { - return; - } - CallDepthThreadLocalMap.reset(MessageProducer.class); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsSessionInstrumentation.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsSessionInstrumentation.java deleted file mode 100644 index 0d307c064e..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsSessionInstrumentation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import javax.jms.Destination; -import javax.jms.MessageConsumer; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class JmsSessionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.jms.Session"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.jms.Session")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("createConsumer") - .and(takesArgument(0, named("javax.jms.Destination"))) - .and(isPublic()), - JmsSessionInstrumentation.class.getName() + "$ConsumerAdvice"); - } - - public static class ConsumerAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(0) Destination destination, @Advice.Return MessageConsumer consumer) { - MessageDestination messageDestination = JmsTracer.extractMessageDestination(destination); - InstrumentationContext.get(MessageConsumer.class, MessageDestination.class) - .put(consumer, messageDestination); - } - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsTracer.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsTracer.java deleted file mode 100644 index 2af177ab89..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsTracer.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import static io.opentelemetry.api.OpenTelemetry.getGlobalPropagators; -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER; -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER; -import static io.opentelemetry.javaagent.instrumentation.jms.MessageExtractAdapter.GETTER; -import static io.opentelemetry.javaagent.instrumentation.jms.MessageInjectAdapter.SETTER; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.util.concurrent.TimeUnit; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Queue; -import javax.jms.TemporaryQueue; -import javax.jms.TemporaryTopic; -import javax.jms.Topic; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class JmsTracer extends BaseTracer { - private static final Logger log = LoggerFactory.getLogger(JmsTracer.class); - - // From the spec - public static final String TEMP_DESTINATION_NAME = "(temporary)"; - - private static final JmsTracer TRACER = new JmsTracer(); - - public static JmsTracer tracer() { - return TRACER; - } - - public Span startConsumerSpan( - MessageDestination destination, String operation, Message message, long startTime) { - SpanBuilder spanBuilder = - tracer - .spanBuilder(spanName(destination, operation)) - .setSpanKind(CONSUMER) - .setStartTimestamp(startTime, TimeUnit.MILLISECONDS) - .setAttribute(SemanticAttributes.MESSAGING_OPERATION, operation); - - if (message != null && "process".equals(operation)) { - // TODO use BaseTracer.extract() which has context leak detection - // (and fix the context leak that it is currently detecting when running Jms2Test) - Context context = - getGlobalPropagators().getTextMapPropagator().extract(Context.root(), message, GETTER); - SpanContext spanContext = Span.fromContext(context).getSpanContext(); - if (spanContext.isValid()) { - spanBuilder.setParent(context); - } - } - - Span span = spanBuilder.startSpan(); - afterStart(span, destination, message); - return span; - } - - public Span startProducerSpan(MessageDestination destination, Message message) { - Span span = tracer.spanBuilder(spanName(destination, "send")).setSpanKind(PRODUCER).startSpan(); - afterStart(span, destination, message); - return span; - } - - public Scope startProducerScope(Span span, Message message) { - Context context = Context.current().with(span); - OpenTelemetry.getGlobalPropagators().getTextMapPropagator().inject(context, message, SETTER); - return context.makeCurrent(); - } - - public String spanName(MessageDestination destination, String operation) { - if (destination.temporary) { - return TEMP_DESTINATION_NAME + " " + operation; - } else { - return destination.destinationName + " " + operation; - } - } - - private static final String TIBCO_TMP_PREFIX = "$TMP$"; - - public MessageDestination extractDestination(Message message, Destination fallbackDestination) { - Destination jmsDestination = null; - try { - jmsDestination = message.getJMSDestination(); - } catch (Exception ignored) { - } - - if (jmsDestination == null) { - jmsDestination = fallbackDestination; - } - - return extractMessageDestination(jmsDestination); - } - - public static MessageDestination extractMessageDestination(Destination destination) { - if (destination instanceof Queue) { - String queueName; - try { - queueName = ((Queue) destination).getQueueName(); - } catch (JMSException e) { - queueName = "unknown"; - } - - boolean temporary = - destination instanceof TemporaryQueue || queueName.startsWith(TIBCO_TMP_PREFIX); - - return new MessageDestination(queueName, "queue", temporary); - } - - if (destination instanceof Topic) { - String topicName; - try { - topicName = ((Topic) destination).getTopicName(); - } catch (JMSException e) { - topicName = "unknown"; - } - - boolean temporary = - destination instanceof TemporaryTopic || topicName.startsWith(TIBCO_TMP_PREFIX); - - return new MessageDestination(topicName, "topic", temporary); - } - - return MessageDestination.UNKNOWN; - } - - private void afterStart(Span span, MessageDestination destination, Message message) { - span.setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "jms"); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, destination.destinationKind); - if (destination.temporary) { - span.setAttribute(SemanticAttributes.MESSAGING_TEMP_DESTINATION, true); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, TEMP_DESTINATION_NAME); - } else { - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, destination.destinationName); - } - - if (message != null) { - try { - String messageId = message.getJMSMessageID(); - if (messageId != null) { - span.setAttribute(SemanticAttributes.MESSAGING_MESSAGE_ID, messageId); - } - } catch (Exception e) { - log.debug("Failure getting JMS message id", e); - } - - try { - String correlationId = message.getJMSCorrelationID(); - if (correlationId != null) { - span.setAttribute(SemanticAttributes.MESSAGING_CONVERSATION_ID, correlationId); - } - } catch (Exception e) { - log.debug("Failure getting JMS correlation id", e); - } - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jms"; - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageDestination.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageDestination.java deleted file mode 100644 index 662913e85d..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageDestination.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -public class MessageDestination { - public static final MessageDestination UNKNOWN = - new MessageDestination("unknown", "unknown", false); - - public final String destinationName; - public final String destinationKind; - public final boolean temporary; - - public MessageDestination(String destinationName, String destinationKind, boolean temporary) { - this.destinationName = destinationName; - this.destinationKind = destinationKind; - this.temporary = temporary; - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageExtractAdapter.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageExtractAdapter.java deleted file mode 100644 index 6d35b08401..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageExtractAdapter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.util.Collections; -import javax.jms.JMSException; -import javax.jms.Message; - -public class MessageExtractAdapter implements TextMapPropagator.Getter { - - public static final MessageExtractAdapter GETTER = new MessageExtractAdapter(); - - @Override - public Iterable keys(Message message) { - try { - return Collections.list(message.getPropertyNames()); - } catch (JMSException e) { - return Collections.emptyList(); - } - } - - @Override - public String get(Message carrier, String key) { - String propName = key.replace("-", MessageInjectAdapter.DASH); - Object value; - try { - value = carrier.getObjectProperty(propName); - } catch (JMSException e) { - throw new RuntimeException(e); - } - if (value instanceof String) { - return (String) value; - } else { - return null; - } - } -} diff --git a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageInjectAdapter.java b/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageInjectAdapter.java deleted file mode 100644 index c2c3f843f6..0000000000 --- a/instrumentation/jms-1.1/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageInjectAdapter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jms; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import javax.jms.JMSException; -import javax.jms.Message; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MessageInjectAdapter implements TextMapPropagator.Setter { - - private static final Logger log = LoggerFactory.getLogger(MessageInjectAdapter.class); - - public static final MessageInjectAdapter SETTER = new MessageInjectAdapter(); - - static final String DASH = "__dash__"; - - @Override - public void set(Message carrier, String key, String value) { - String propName = key.replace("-", DASH); - try { - carrier.setStringProperty(propName, value); - } catch (JMSException e) { - if (log.isDebugEnabled()) { - log.debug("Failure setting jms property: " + propName, e); - } - } - } -} diff --git a/instrumentation/jms-1.1/src/test/groovy/Jms1Test.groovy b/instrumentation/jms-1.1/src/test/groovy/Jms1Test.groovy deleted file mode 100644 index ca81a2ba13..0000000000 --- a/instrumentation/jms-1.1/src/test/groovy/Jms1Test.groovy +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.javaagent.instrumentation.jms.JmsTracer -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.concurrent.CountDownLatch -import java.util.concurrent.atomic.AtomicReference -import javax.jms.Connection -import javax.jms.Message -import javax.jms.MessageListener -import javax.jms.Session -import javax.jms.TextMessage -import org.apache.activemq.ActiveMQConnectionFactory -import org.apache.activemq.command.ActiveMQTextMessage -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.testcontainers.containers.GenericContainer -import org.testcontainers.containers.output.Slf4jLogConsumer -import spock.lang.Shared - -class Jms1Test extends AgentTestRunner { - - private static final Logger logger = LoggerFactory.getLogger(Jms1Test) - - private static final GenericContainer broker = new GenericContainer("rmohr/activemq:latest") - .withExposedPorts(61616, 8161) - .withLogConsumer(new Slf4jLogConsumer(logger)) - - @Shared - String messageText = "a message" - @Shared - Session session - - ActiveMQTextMessage message = session.createTextMessage(messageText) - - def setupSpec() { - broker.start() - ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:" + broker.getMappedPort(61616)) - - Connection connection = connectionFactory.createConnection() - connection.start() - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE) - } - - def cleanupSpec() { - broker.stop() - } - - def "sending a message to #destinationName #destinationType generates spans"() { - setup: - def producer = session.createProducer(destination) - def consumer = session.createConsumer(destination) - - producer.send(message) - - TextMessage receivedMessage = consumer.receive() - String messageId = receivedMessage.getJMSMessageID() - - expect: - receivedMessage.text == messageText - assertTraces(2) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - consumerSpan(it, 0, destinationType, destinationName, messageId, null, "receive") - } - } - - cleanup: - producer.close() - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - session.createTemporaryQueue() | "queue" | JmsTracer.TEMP_DESTINATION_NAME - session.createTemporaryTopic() | "topic" | JmsTracer.TEMP_DESTINATION_NAME - } - - def "sending to a MessageListener on #destinationName #destinationType generates a span"() { - setup: - def lock = new CountDownLatch(1) - def messageRef = new AtomicReference() - def producer = session.createProducer(destination) - def consumer = session.createConsumer(destination) - consumer.setMessageListener new MessageListener() { - @Override - void onMessage(Message message) { - lock.await() // ensure the producer trace is reported first. - messageRef.set(message) - } - } - - producer.send(message) - lock.countDown() - - expect: - assertTraces(1) { - trace(0, 2) { - producerSpan(it, 0, destinationType, destinationName) - consumerSpan(it, 1, destinationType, destinationName, messageRef.get().getJMSMessageID(), span(0), "process") - } - } - // This check needs to go after all traces have been accounted for - messageRef.get().text == messageText - - cleanup: - producer.close() - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - session.createTemporaryQueue() | "queue" | JmsTracer.TEMP_DESTINATION_NAME - session.createTemporaryTopic() | "topic" | JmsTracer.TEMP_DESTINATION_NAME - } - - def "failing to receive message with receiveNoWait on #destinationName #destinationType works"() { - setup: - def consumer = session.createConsumer(destination) - - // Receive with timeout - TextMessage receivedMessage = consumer.receiveNoWait() - - expect: - receivedMessage == null - assertTraces(1) { - trace(0, 1) { // Consumer trace - span(0) { - hasNoParent() - name destinationName + " receive" - kind CONSUMER - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" - } - } - } - } - - cleanup: - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - } - - def "failing to receive message with wait(timeout) on #destinationName #destinationType works"() { - setup: - def consumer = session.createConsumer(destination) - - // Receive with timeout - TextMessage receivedMessage = consumer.receive(100) - - expect: - receivedMessage == null - assertTraces(1) { - trace(0, 1) { // Consumer trace - span(0) { - hasNoParent() - name destinationName + " receive" - kind CONSUMER - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" - } - } - } - } - - cleanup: - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - } - - def "sending a read-only message to #destinationName #destinationType fails"() { - setup: - def producer = session.createProducer(destination) - def consumer = session.createConsumer(destination) - - expect: - !message.isReadOnlyProperties() - - when: - message.setReadOnlyProperties(true) - and: - producer.send(message) - - TextMessage receivedMessage = consumer.receive() - - then: - receivedMessage.text == messageText - - // This will result in a logged failure because we tried to - // write properties in MessagePropertyTextMap when readOnlyProperties = true. - // The consumer span will also not be linked to the parent. - assertTraces(2) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - span(0) { - hasNoParent() - name destinationName + " receive" - kind CONSUMER - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_MESSAGE_ID.key}" receivedMessage.getJMSMessageID() - "${SemanticAttributes.MESSAGING_OPERATION.key}" "receive" - if (destinationName == JmsTracer.TEMP_DESTINATION_NAME) { - "${SemanticAttributes.MESSAGING_TEMP_DESTINATION.key}" true - } - } - } - } - } - - cleanup: - producer.close() - consumer.close() - - where: - destination | destinationType | destinationName - session.createQueue("someQueue") | "queue" | "someQueue" - session.createTopic("someTopic") | "topic" | "someTopic" - session.createTemporaryQueue() | "queue" | JmsTracer.TEMP_DESTINATION_NAME - session.createTemporaryTopic() | "topic" | JmsTracer.TEMP_DESTINATION_NAME - } - - static producerSpan(TraceAssert trace, int index, String destinationType, String destinationName) { - trace.span(index) { - name destinationName + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - if (destinationName == JmsTracer.TEMP_DESTINATION_NAME) { - "${SemanticAttributes.MESSAGING_TEMP_DESTINATION.key}" true - } - } - } - } - - // passing messageId = null will verify message.id is not captured, - // passing messageId = "" will verify message.id is captured (but won't verify anything about the value), - // any other value for messageId will verify that message.id is captured and has that same value - static consumerSpan(TraceAssert trace, int index, String destinationType, String destinationName, String messageId, Object parentOrLinkedSpan, String operation) { - trace.span(index) { - name destinationName + " " + operation - kind CONSUMER - if (parentOrLinkedSpan != null) { - childOf((SpanData) parentOrLinkedSpan) - } else { - hasNoParent() - } - errored false - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "jms" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" destinationName - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" destinationType - "${SemanticAttributes.MESSAGING_OPERATION.key}" operation - if (messageId != null) { - //In some tests we don't know exact messageId, so we pass "" and verify just the existence of the attribute - "${SemanticAttributes.MESSAGING_MESSAGE_ID.key}" { it == messageId || messageId == "" } - } - if (destinationName == JmsTracer.TEMP_DESTINATION_NAME) { - "${SemanticAttributes.MESSAGING_TEMP_DESTINATION.key}" true - } - } - } - } -} diff --git a/instrumentation/jms-1.1/src/test/groovy/SpringListenerJms1Test.groovy b/instrumentation/jms-1.1/src/test/groovy/SpringListenerJms1Test.groovy deleted file mode 100644 index 22a0b89001..0000000000 --- a/instrumentation/jms-1.1/src/test/groovy/SpringListenerJms1Test.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Jms1Test.consumerSpan -import static Jms1Test.producerSpan - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import javax.jms.ConnectionFactory -import listener.Config -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.jms.core.JmsTemplate - -class SpringListenerJms1Test extends AgentTestRunner { - - def "receiving message in spring listener generates spans"() { - setup: - def context = new AnnotationConfigApplicationContext(Config) - def factory = context.getBean(ConnectionFactory) - def template = new JmsTemplate(factory) - template.convertAndSend("SpringListenerJms1", "a message") - - expect: - assertTraces(2) { - trace(0, 2) { - producerSpan(it, 0, "queue", "SpringListenerJms1") - consumerSpan(it, 1, "queue", "SpringListenerJms1", "", span(0), "process") - } - trace(1, 1) { - consumerSpan(it, 0, "queue", "SpringListenerJms1", "", null, "receive") - } - } - - cleanup: - context.stop() - } -} diff --git a/instrumentation/jms-1.1/src/test/groovy/SpringTemplateJms1Test.groovy b/instrumentation/jms-1.1/src/test/groovy/SpringTemplateJms1Test.groovy deleted file mode 100644 index 7ab96ea001..0000000000 --- a/instrumentation/jms-1.1/src/test/groovy/SpringTemplateJms1Test.groovy +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static Jms1Test.consumerSpan -import static Jms1Test.producerSpan - -import com.google.common.base.Stopwatch -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.javaagent.instrumentation.jms.JmsTracer -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicReference -import javax.jms.Connection -import javax.jms.Session -import javax.jms.TextMessage -import org.apache.activemq.ActiveMQConnectionFactory -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.jms.core.JmsTemplate -import org.testcontainers.containers.GenericContainer -import org.testcontainers.containers.output.Slf4jLogConsumer -import spock.lang.Shared - -class SpringTemplateJms1Test extends AgentTestRunner { - private static final Logger logger = LoggerFactory.getLogger(SpringTemplateJms1Test) - - private static final GenericContainer broker = new GenericContainer("rmohr/activemq:latest") - .withExposedPorts(61616, 8161) - .withLogConsumer(new Slf4jLogConsumer(logger)) - - @Shared - String messageText = "a message" - @Shared - JmsTemplate template - @Shared - Session session - - def setupSpec() { - broker.start() - ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:" + broker.getMappedPort(61616)) - Connection connection = connectionFactory.createConnection() - connection.start() - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE) - - template = new JmsTemplate(connectionFactory) - // Make this longer than timeout on TEST_WRITER.waitForTraces - // Otherwise caller might give up waiting before callee has a chance to respond. - template.receiveTimeout = TimeUnit.SECONDS.toMillis(21) - } - - def cleanupSpec() { - broker.stop() - } - - def "sending a message to #destinationName generates spans"() { - setup: - template.convertAndSend(destination, messageText) - TextMessage receivedMessage = template.receive(destination) - - expect: - receivedMessage.text == messageText - assertTraces(2) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - consumerSpan(it, 0, destinationType, destinationName, receivedMessage.getJMSMessageID(), null, "receive") - } - } - - where: - destination | destinationType | destinationName - session.createQueue("SpringTemplateJms1") | "queue" | "SpringTemplateJms1" - } - - def "send and receive message generates spans"() { - setup: - AtomicReference msgId = new AtomicReference<>() - Thread.start { - TextMessage msg = template.receive(destination) - assert msg.text == messageText - msgId.set(msg.getJMSMessageID()) - - template.send(msg.getJMSReplyTo()) { - session -> template.getMessageConverter().toMessage("responded!", session) - } - } - def receivedMessage - def stopwatch = Stopwatch.createStarted() - while (receivedMessage == null && stopwatch.elapsed(TimeUnit.SECONDS) < 10) { - // sendAndReceive() returns null if template.receive() has not been called yet - receivedMessage = template.sendAndReceive(destination) { - session -> template.getMessageConverter().toMessage(messageText, session) - } - } - - expect: - receivedMessage.text == "responded!" - assertTraces(4) { - trace(0, 1) { - producerSpan(it, 0, destinationType, destinationName) - } - trace(1, 1) { - consumerSpan(it, 0, destinationType, destinationName, msgId.get(), null, "receive") - } - trace(2, 1) { - // receive doesn't propagate the trace, so this is a root - producerSpan(it, 0, "queue", JmsTracer.TEMP_DESTINATION_NAME) - } - trace(3, 1) { - consumerSpan(it, 0, "queue", JmsTracer.TEMP_DESTINATION_NAME, receivedMessage.getJMSMessageID(), null, "receive") - } - } - - where: - destination | destinationType | destinationName - session.createQueue("SpringTemplateJms1") | "queue" | "SpringTemplateJms1" - } -} diff --git a/instrumentation/jms-1.1/src/test/groovy/listener/Config.groovy b/instrumentation/jms-1.1/src/test/groovy/listener/Config.groovy deleted file mode 100644 index 24e6cbf209..0000000000 --- a/instrumentation/jms-1.1/src/test/groovy/listener/Config.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package listener - -import javax.annotation.PreDestroy -import javax.jms.ConnectionFactory -import org.apache.activemq.ActiveMQConnectionFactory -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration -import org.springframework.jms.annotation.EnableJms -import org.springframework.jms.config.DefaultJmsListenerContainerFactory -import org.springframework.jms.config.JmsListenerContainerFactory -import org.testcontainers.containers.GenericContainer - -@Configuration -@ComponentScan -@EnableJms -class Config { - - private static GenericContainer broker = new GenericContainer("rmohr/activemq:latest") - .withExposedPorts(61616, 8161) - - static { - broker.start() - } - - @Bean - ConnectionFactory connectionFactory() { - return new ActiveMQConnectionFactory("tcp://localhost:" + broker.getMappedPort(61616)) - } - - @Bean - JmsListenerContainerFactory containerFactory(ConnectionFactory connectionFactory) { - DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory() - factory.setConnectionFactory(connectionFactory) - return factory - } - - @PreDestroy - void destroy() { - broker.stop() - } -} diff --git a/instrumentation/jms-1.1/src/test/groovy/listener/TestListener.groovy b/instrumentation/jms-1.1/src/test/groovy/listener/TestListener.groovy deleted file mode 100644 index 2d76748830..0000000000 --- a/instrumentation/jms-1.1/src/test/groovy/listener/TestListener.groovy +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package listener - -import org.springframework.jms.annotation.JmsListener -import org.springframework.stereotype.Component - -@Component -class TestListener { - - @JmsListener(destination = "SpringListenerJms1", containerFactory = "containerFactory") - void receiveMessage(String message) { - println "received: " + message - } -} diff --git a/instrumentation/jsp-2.3/jsp-2.3.gradle b/instrumentation/jsp-2.3/jsp-2.3.gradle deleted file mode 100644 index b3c954a24e..0000000000 --- a/instrumentation/jsp-2.3/jsp-2.3.gradle +++ /dev/null @@ -1,30 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.tomcat" - module = "tomcat-jasper" - // range [7.0.0,7.0.19) and version 8.0.9 missing from maven - versions = "[7.0.19,8.0.9),(8.0.9,)" - } -} - -dependencies { - // compiling against tomcat 7.0.20 because there seems to be some issues with Tomcat's dependency < 7.0.20 - compileOnly group: 'org.apache.tomcat', name: 'tomcat-jasper', version: '7.0.20' - compileOnly group: 'javax.servlet.jsp', name: 'javax.servlet.jsp-api', version: '2.3.0' - compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0' - - testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') - // using tomcat 7.0.37 because there seems to be some issues with Tomcat's jar scanning in versions < 7.0.37 - // https://stackoverflow.com/questions/23484098/org-apache-tomcat-util-bcel-classfile-classformatexception-invalid-byte-tag-in - testLibrary group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '7.0.37' - testLibrary group: 'org.apache.tomcat.embed', name: 'tomcat-embed-logging-juli', version: '7.0.37' - testLibrary group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '7.0.37' - - latestDepTestLibrary group: 'javax.servlet.jsp', name: 'javax.servlet.jsp-api', version: '+' - latestDepTestLibrary group: 'javax.servlet', name: 'javax.servlet-api', version: '+' - latestDepTestLibrary group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '9.+' - latestDepTestLibrary group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.+' - latestDepTestLibrary group: 'org.apache.tomcat.embed', name: 'tomcat-embed-logging-juli', version: '9.+' -} diff --git a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentation.java b/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentation.java deleted file mode 100644 index 2c395df8e1..0000000000 --- a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentation.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jsp; - -import static io.opentelemetry.javaagent.instrumentation.jsp.JspTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class HttpJspPageInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("javax.servlet.jsp.HttpJspPage"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("javax.servlet.jsp.HttpJspPage")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("_jspService") - .and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))) - .and(takesArgument(1, named("javax.servlet.http.HttpServletResponse"))) - .and(isPublic()), - HttpJspPageInstrumentation.class.getName() + "$HttpJspPageAdvice"); - } - - public static class HttpJspPageAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) HttpServletRequest req, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(tracer().spanNameOnRender(req), Kind.INTERNAL); - tracer().onRender(span, req); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentation.java b/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentation.java deleted file mode 100644 index cdc93729ae..0000000000 --- a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentation.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jsp; - -import static io.opentelemetry.javaagent.instrumentation.jsp.JspTracer.tracer; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.jasper.JspCompilationContext; - -public class JspCompilationContextInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.jasper.JspCompilationContext"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("compile").and(takesArguments(0)).and(isPublic()), - JspCompilationContextInstrumentation.class.getName() + "$JasperJspCompilationContext"); - } - - public static class JasperJspCompilationContext { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This JspCompilationContext jspCompilationContext, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(tracer().spanNameOnCompile(jspCompilationContext), Kind.INTERNAL); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.This JspCompilationContext jspCompilationContext, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - // Decorate on return because additional properties are available - tracer().onCompile(span, jspCompilationContext); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationModule.java b/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationModule.java deleted file mode 100644 index c38ceeb95b..0000000000 --- a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationModule.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jsp; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class JspInstrumentationModule extends InstrumentationModule { - public JspInstrumentationModule() { - super("jsp"); - } - - @Override - public List typeInstrumentations() { - return asList(new HttpJspPageInstrumentation(), new JspCompilationContextInstrumentation()); - } -} diff --git a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspTracer.java b/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspTracer.java deleted file mode 100644 index cd6f2de88e..0000000000 --- a/instrumentation/jsp-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspTracer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jsp; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.net.URI; -import java.net.URISyntaxException; -import javax.servlet.RequestDispatcher; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.jsp.HttpJspPage; -import org.apache.jasper.JspCompilationContext; -import org.apache.jasper.compiler.Compiler; -import org.slf4j.LoggerFactory; - -public class JspTracer extends BaseTracer { - private static final JspTracer TRACER = new JspTracer(); - - public static JspTracer tracer() { - return TRACER; - } - - public String spanNameOnCompile(JspCompilationContext jspCompilationContext) { - return jspCompilationContext == null - ? "Compile" - : "Compile " + jspCompilationContext.getJspFile(); - } - - public void onCompile(Span span, JspCompilationContext jspCompilationContext) { - if (jspCompilationContext != null) { - Compiler compiler = jspCompilationContext.getCompiler(); - if (compiler != null) { - span.setAttribute("jsp.compiler", compiler.getClass().getName()); - } - span.setAttribute("jsp.classFQCN", jspCompilationContext.getFQCN()); - } - } - - public String spanNameOnRender(HttpServletRequest req) { - // get the JSP file name being rendered in an include action - Object includeServletPath = req.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); - String spanName = req.getServletPath(); - if (includeServletPath instanceof String) { - spanName = includeServletPath.toString(); - } - return "Render " + spanName; - } - - public void onRender(Span span, HttpServletRequest req) { - Object forwardOrigin = req.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH); - if (forwardOrigin instanceof String) { - span.setAttribute("jsp.forwardOrigin", forwardOrigin.toString()); - } - - // add the request URL as a tag to provide better context when looking at spans produced by - // actions. Tomcat 9 has relative path symbols in the value returned from - // HttpServletRequest#getRequestURL(), - // normalizing the URL should remove those symbols for readability and consistency - try { - span.setAttribute( - "jsp.requestURL", (new URI(req.getRequestURL().toString())).normalize().toString()); - } catch (URISyntaxException e) { - LoggerFactory.getLogger(HttpJspPage.class) - .warn("Failed to get and normalize request URL: " + e.getMessage()); - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.jsp"; - } -} diff --git a/instrumentation/jsp-2.3/src/test/groovy/JspInstrumentationBasicTests.groovy b/instrumentation/jsp-2.3/src/test/groovy/JspInstrumentationBasicTests.groovy deleted file mode 100644 index aa0d62bae1..0000000000 --- a/instrumentation/jsp-2.3/src/test/groovy/JspInstrumentationBasicTests.groovy +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.SERVER - -import com.google.common.io.Files -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.OkHttpUtils -import io.opentelemetry.instrumentation.test.utils.PortUtils -import okhttp3.MultipartBody -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.RequestBody -import okhttp3.Response -import org.apache.catalina.Context -import org.apache.catalina.startup.Tomcat -import org.apache.jasper.JasperException -import spock.lang.Shared -import spock.lang.Unroll - -//TODO should this be HttpServerTest? -class JspInstrumentationBasicTests extends AgentTestRunner { - - static { - // skip jar scanning using environment variables: - // http://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html#JAR_Scanning - // having this set allows us to test with old versions of the tomcat api since - // JarScanFilter did not exist in the tomcat 7 api - System.setProperty("org.apache.catalina.startup.ContextConfig.jarsToSkip", "*") - System.setProperty("org.apache.catalina.startup.TldConfig.jarsToSkip", "*") - } - - @Shared - int port - @Shared - Tomcat tomcatServer - @Shared - Context appContext - @Shared - String jspWebappContext = "jsptest-context" - - @Shared - File baseDir - @Shared - String baseUrl - - OkHttpClient client = OkHttpUtils.client() - - def setupSpec() { - baseDir = Files.createTempDir() - baseDir.deleteOnExit() - - port = PortUtils.randomOpenPort() - - tomcatServer = new Tomcat() - tomcatServer.setBaseDir(baseDir.getAbsolutePath()) - tomcatServer.setPort(port) - tomcatServer.getConnector() - // comment to debug - tomcatServer.setSilent(true) - // this is needed in tomcat 9, this triggers the creation of a connector, will not - // affect tomcat 7 and 8 - // https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed - tomcatServer.getConnector() - baseUrl = "http://localhost:$port/$jspWebappContext" - - appContext = tomcatServer.addWebapp("/$jspWebappContext", - JspInstrumentationBasicTests.getResource("/webapps/jsptest").getPath()) - - tomcatServer.start() - System.out.println( - "Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + port + "/") - } - - def cleanupSpec() { - tomcatServer.stop() - tomcatServer.destroy() - } - - @Unroll - def "non-erroneous GET #test test"() { - setup: - String reqUrl = baseUrl + "/$jspFileName" - def req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/$jspFileName" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/$jspFileName" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /$jspFileName" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspClassNamePrefix$jspClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /$jspFileName" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - - where: - test | jspFileName | jspClassName | jspClassNamePrefix - "no java jsp" | "nojava.jsp" | "nojava_jsp" | "" - "basic loop jsp" | "common/loop.jsp" | "loop_jsp" | "common." - "invalid HTML markup" | "invalidMarkup.jsp" | "invalidMarkup_jsp" | "" - } - - def "non-erroneous GET with query string"() { - setup: - String queryString = "HELLO" - String reqUrl = baseUrl + "/getQuery.jsp" - Request req = new Request.Builder().url(new URL(reqUrl + "?" + queryString)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/getQuery.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/getQuery.jsp?$queryString" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /getQuery.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.getQuery_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /getQuery.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - def "non-erroneous POST"() { - setup: - String reqUrl = baseUrl + "/post.jsp" - RequestBody requestBody = new MultipartBody.Builder() - .setType(MultipartBody.FORM) - .addFormDataPart("name", "world") - .build() - Request req = new Request.Builder().url(new URL(reqUrl)).post(requestBody).build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/post.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/post.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "POST" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /post.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.post_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /post.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - @Unroll - def "erroneous runtime errors GET jsp with #test test"() { - setup: - String reqUrl = baseUrl + "/$jspFileName" - def req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/$jspFileName" - kind SERVER - errored true - event(0) { - eventName(SemanticAttributes.EXCEPTION_EVENT_NAME) - attributes { - "${SemanticAttributes.EXCEPTION_TYPE.key()}" { String tagExceptionType -> - return tagExceptionType == exceptionClass.getName() || tagExceptionType.contains(exceptionClass.getSimpleName()) - } - "${SemanticAttributes.EXCEPTION_MESSAGE.key()}" { String tagErrorMsg -> - return errorMessageOptional || tagErrorMsg instanceof String - } - "${SemanticAttributes.EXCEPTION_STACKTRACE.key()}" String - } - } - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/$jspFileName" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 500 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /$jspFileName" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /$jspFileName" - errored true - event(0) { - eventName(SemanticAttributes.EXCEPTION_EVENT_NAME) - attributes { - "${SemanticAttributes.EXCEPTION_TYPE.key()}" { String tagExceptionType -> - return tagExceptionType == exceptionClass.getName() || tagExceptionType.contains(exceptionClass.getSimpleName()) - } - "${SemanticAttributes.EXCEPTION_MESSAGE.key()}" { String tagErrorMsg -> - return errorMessageOptional || tagErrorMsg instanceof String - } - "${SemanticAttributes.EXCEPTION_STACKTRACE.key()}" String - } - } - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 500 - - cleanup: - res.close() - - where: - test | jspFileName | jspClassName | exceptionClass | errorMessageOptional - "java runtime error" | "runtimeError.jsp" | "runtimeError_jsp" | ArithmeticException | false - "invalid write" | "invalidWrite.jsp" | "invalidWrite_jsp" | IndexOutOfBoundsException | true - "missing query gives null" | "getQuery.jsp" | "getQuery_jsp" | NullPointerException | true - } - - def "non-erroneous include plain HTML GET"() { - setup: - String reqUrl = baseUrl + "/includes/includeHtml.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/includes/includeHtml.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/includes/includeHtml.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /includes/includeHtml.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.includes.includeHtml_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /includes/includeHtml.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - def "non-erroneous multi GET"() { - setup: - String reqUrl = baseUrl + "/includes/includeMulti.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 7) { - span(0) { - hasNoParent() - name "/$jspWebappContext/includes/includeMulti.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/includes/includeMulti.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /includes/includeMulti.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.includes.includeMulti_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /includes/includeMulti.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - span(3) { - childOf span(2) - name "Compile /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - span(5) { - childOf span(2) - name "Compile /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(6) { - childOf span(2) - name "Render /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - def "#test compile error should not produce render traces and spans"() { - setup: - String reqUrl = baseUrl + "/$jspFileName" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - hasNoParent() - name "/$jspWebappContext/$jspFileName" - kind SERVER - errored true - errorEvent(JasperException, String) - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/$jspFileName" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 500 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /$jspFileName" - errored true - errorEvent(JasperException, String) - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspClassNamePrefix$jspClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - } - } - res.code() == 500 - - cleanup: - res.close() - - where: - test | jspFileName | jspClassName | jspClassNamePrefix - "normal" | "compileError.jsp" | "compileError_jsp" | "" - "forward" | "forwards/forwardWithCompileError.jsp" | "forwardWithCompileError_jsp" | "forwards." - } - - def "direct static file reference"() { - setup: - String reqUrl = baseUrl + "/$staticFile" - def req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - res.code() == 200 - assertTraces(1) { - trace(0, 1) { - span(0) { - hasNoParent() - name "/$jspWebappContext/$staticFile" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/$staticFile" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - } - } - - cleanup: - res.close() - - where: - staticFile = "common/hello.html" - } -} diff --git a/instrumentation/jsp-2.3/src/test/groovy/JspInstrumentationForwardTests.groovy b/instrumentation/jsp-2.3/src/test/groovy/JspInstrumentationForwardTests.groovy deleted file mode 100644 index 5baf1756ac..0000000000 --- a/instrumentation/jsp-2.3/src/test/groovy/JspInstrumentationForwardTests.groovy +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.SERVER - -import com.google.common.io.Files -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.OkHttpUtils -import io.opentelemetry.instrumentation.test.utils.PortUtils -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.apache.catalina.Context -import org.apache.catalina.startup.Tomcat -import org.apache.jasper.JasperException -import spock.lang.Shared -import spock.lang.Unroll - -class JspInstrumentationForwardTests extends AgentTestRunner { - - static { - // skip jar scanning using environment variables: - // http://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html#JAR_Scanning - // having this set allows us to test with old versions of the tomcat api since - // JarScanFilter did not exist in the tomcat 7 api - System.setProperty("org.apache.catalina.startup.ContextConfig.jarsToSkip", "*") - System.setProperty("org.apache.catalina.startup.TldConfig.jarsToSkip", "*") - } - - @Shared - int port - @Shared - Tomcat tomcatServer - @Shared - Context appContext - @Shared - String jspWebappContext = "jsptest-context" - - @Shared - File baseDir - @Shared - String baseUrl - - OkHttpClient client = OkHttpUtils.client() - - def setupSpec() { - baseDir = Files.createTempDir() - baseDir.deleteOnExit() - - port = PortUtils.randomOpenPort() - - tomcatServer = new Tomcat() - tomcatServer.setBaseDir(baseDir.getAbsolutePath()) - tomcatServer.setPort(port) - tomcatServer.getConnector() - // comment to debug - tomcatServer.setSilent(true) - // this is needed in tomcat 9, this triggers the creation of a connector, will not - // affect tomcat 7 and 8 - // https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed - tomcatServer.getConnector() - - baseUrl = "http://localhost:$port/$jspWebappContext" - - appContext = tomcatServer.addWebapp("/$jspWebappContext", - JspInstrumentationForwardTests.getResource("/webapps/jsptest").getPath()) - - tomcatServer.start() - System.out.println( - "Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + port + "/") - } - - def cleanupSpec() { - tomcatServer.stop() - tomcatServer.destroy() - } - - @Unroll - def "non-erroneous GET forward to #forwardTo"() { - setup: - String reqUrl = baseUrl + "/$forwardFromFileName" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 5) { - span(0) { - hasNoParent() - name "/$jspWebappContext/$forwardFromFileName" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/$forwardFromFileName" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /$forwardFromFileName" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspForwardFromClassPrefix$jspForwardFromClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /$forwardFromFileName" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - span(3) { - childOf span(2) - name "Compile /$forwardDestFileName" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspForwardDestClassPrefix$jspForwardDestClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /$forwardDestFileName" - errored false - attributes { - "jsp.forwardOrigin" "/$forwardFromFileName" - "jsp.requestURL" baseUrl + "/$forwardDestFileName" - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - - where: - forwardTo | forwardFromFileName | forwardDestFileName | jspForwardFromClassName | jspForwardFromClassPrefix | jspForwardDestClassName | jspForwardDestClassPrefix - "no java jsp" | "forwards/forwardToNoJavaJsp.jsp" | "nojava.jsp" | "forwardToNoJavaJsp_jsp" | "forwards." | "nojava_jsp" | "" - "normal java jsp" | "forwards/forwardToSimpleJava.jsp" | "common/loop.jsp" | "forwardToSimpleJava_jsp" | "forwards." | "loop_jsp" | "common." - } - - def "non-erroneous GET forward to plain HTML"() { - setup: - String reqUrl = baseUrl + "/forwards/forwardToHtml.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/forwards/forwardToHtml.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/forwards/forwardToHtml.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToHtml.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToHtml_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToHtml.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - def "non-erroneous GET forwarded to jsp with multiple includes"() { - setup: - String reqUrl = baseUrl + "/forwards/forwardToIncludeMulti.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 9) { - span(0) { - hasNoParent() - name "/$jspWebappContext/forwards/forwardToIncludeMulti.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/forwards/forwardToIncludeMulti.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToIncludeMulti.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToIncludeMulti_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToIncludeMulti.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - span(3) { - childOf span(2) - name "Compile /includes/includeMulti.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.includes.includeMulti_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /includes/includeMulti.jsp" - errored false - attributes { - "jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp" - "jsp.requestURL" baseUrl + "/includes/includeMulti.jsp" - } - } - span(5) { - childOf span(4) - name "Compile /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(6) { - childOf span(4) - name "Render /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp" - "jsp.requestURL" baseUrl + "/includes/includeMulti.jsp" - } - } - span(7) { - childOf span(4) - name "Compile /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(8) { - childOf span(4) - name "Render /common/javaLoopH2.jsp" - errored false - attributes { - "jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp" - "jsp.requestURL" baseUrl + "/includes/includeMulti.jsp" - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - def "non-erroneous GET forward to another forward (2 forwards)"() { - setup: - String reqUrl = baseUrl + "/forwards/forwardToJspForward.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 7) { - span(0) { - hasNoParent() - name "/$jspWebappContext/forwards/forwardToJspForward.jsp" - kind SERVER - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/forwards/forwardToJspForward.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToJspForward.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToJspForward_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToJspForward.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - span(3) { - childOf span(2) - name "Compile /forwards/forwardToSimpleJava.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToSimpleJava_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /forwards/forwardToSimpleJava.jsp" - errored false - attributes { - "jsp.forwardOrigin" "/forwards/forwardToJspForward.jsp" - "jsp.requestURL" baseUrl + "/forwards/forwardToSimpleJava.jsp" - } - } - span(5) { - childOf span(4) - name "Compile /common/loop.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.common.loop_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(6) { - childOf span(4) - name "Render /common/loop.jsp" - errored false - attributes { - "jsp.forwardOrigin" "/forwards/forwardToJspForward.jsp" - "jsp.requestURL" baseUrl + "/common/loop.jsp" - } - } - } - } - res.code() == 200 - - cleanup: - res.close() - } - - def "forward to jsp with compile error should not produce a 2nd render span"() { - setup: - String reqUrl = baseUrl + "/forwards/forwardToCompileError.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 4) { - span(0) { - hasNoParent() - name "/$jspWebappContext/forwards/forwardToCompileError.jsp" - kind SERVER - errored true - errorEvent(JasperException, String) - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/forwards/forwardToCompileError.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 500 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToCompileError.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToCompileError_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToCompileError.jsp" - errored true - errorEvent(JasperException, String) - attributes { - "jsp.requestURL" reqUrl - } - } - span(3) { - childOf span(2) - name "Compile /compileError.jsp" - errored true - errorEvent(JasperException, String) - attributes { - "jsp.classFQCN" "org.apache.jsp.compileError_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - } - } - res.code() == 500 - - cleanup: - res.close() - } - - def "forward to non existent jsp should be 404"() { - setup: - String reqUrl = baseUrl + "/forwards/forwardToNonExistent.jsp" - Request req = new Request.Builder().url(new URL(reqUrl)).get().build() - - when: - Response res = client.newCall(req).execute() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - hasNoParent() - name "/$jspWebappContext/forwards/forwardToNonExistent.jsp" - kind SERVER - errored true - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "http://localhost:$port/$jspWebappContext/forwards/forwardToNonExistent.jsp" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 404 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToNonExistent.jsp" - errored false - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToNonExistent_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToNonExistent.jsp" - errored false - attributes { - "jsp.requestURL" reqUrl - } - } - } - } - res.code() == 404 - - cleanup: - res.close() - } -} diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/hello.html b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/hello.html deleted file mode 100644 index 48dd2eff1c..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/hello.html +++ /dev/null @@ -1,9 +0,0 @@ - - - PLAIN HTML - - - -

HELLO!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/javaLoopH2.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/javaLoopH2.jsp deleted file mode 100644 index 7e0bc4f982..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/javaLoopH2.jsp +++ /dev/null @@ -1,7 +0,0 @@ -<% - for (int i = 0; i < 3; ++i) { -%> -

number:<%= i %>

-<% - } -%> diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/loop.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/loop.jsp deleted file mode 100644 index a5e43b7feb..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/common/loop.jsp +++ /dev/null @@ -1,12 +0,0 @@ - - BASIC JSP - - <% - for (int i = 0; i < 3; ++i) { - %> -

number:<%= i %>

- <% - } - %> - - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/compileError.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/compileError.jsp deleted file mode 100644 index 1929ec35df..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/compileError.jsp +++ /dev/null @@ -1,9 +0,0 @@ - -COMPILE ERROR JSP - - <% - FakeClassThatDontExist thingyWithNoSemiColon = abcd - %> -

This will fail

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToCompileError.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToCompileError.jsp deleted file mode 100644 index bdda3e77ed..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToCompileError.jsp +++ /dev/null @@ -1,9 +0,0 @@ - - - - FORWARD TO JSP WITH COMPILE ERROR - - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToHtml.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToHtml.jsp deleted file mode 100644 index 41be4e8923..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToHtml.jsp +++ /dev/null @@ -1,10 +0,0 @@ - - - - FORWARD TO PLAIN HTML - - - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToIncludeMulti.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToIncludeMulti.jsp deleted file mode 100644 index 8c75e2b138..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToIncludeMulti.jsp +++ /dev/null @@ -1,10 +0,0 @@ - - - - FORWARD TO JSP WITH MULTIPLE INCLUDES - - - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToJspForward.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToJspForward.jsp deleted file mode 100644 index e0a95a450f..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToJspForward.jsp +++ /dev/null @@ -1,10 +0,0 @@ - - - - FORWARD TO ANOTHER JSP FORWARD THAT FORWARDS TO SIMPLE JAVA - - - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToNoJavaJsp.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToNoJavaJsp.jsp deleted file mode 100644 index ae33b8f76a..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToNoJavaJsp.jsp +++ /dev/null @@ -1,9 +0,0 @@ - - - - FORWARD TO NO JAVA - - - - - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToNonExistent.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToNonExistent.jsp deleted file mode 100644 index 9e3361ea69..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToNonExistent.jsp +++ /dev/null @@ -1,10 +0,0 @@ - - - - FORWARD TO NON EXISTENT FILE - - - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToSimpleJava.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToSimpleJava.jsp deleted file mode 100644 index 624df742b0..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardToSimpleJava.jsp +++ /dev/null @@ -1,10 +0,0 @@ - - - - FORWARD TO SIMPLE JAVA - - - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardWithCompileError.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardWithCompileError.jsp deleted file mode 100644 index 6af29abab9..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/forwards/forwardWithCompileError.jsp +++ /dev/null @@ -1,12 +0,0 @@ - - - - FORWARD WITH COMPILE ERROR - - <% - FakeNonExistentClass fec = new FakeNonExistentClass() - %> - -

BYE!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/getQuery.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/getQuery.jsp deleted file mode 100644 index 34fd8ab774..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/getQuery.jsp +++ /dev/null @@ -1,14 +0,0 @@ - -GET QUERY JSP - - <% - String query = request.getQueryString(); - %> -

<%= query %>

- <% - if (query.equals("HELLO")) { - out.print("WORLD"); - } - %> - - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/includes/includeHtml.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/includes/includeHtml.jsp deleted file mode 100644 index d8899502b8..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/includes/includeHtml.jsp +++ /dev/null @@ -1,12 +0,0 @@ - - - INCLUDE HTML JSP - - - -
-

INCLUDE HTML

- -
- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/includes/includeMulti.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/includes/includeMulti.jsp deleted file mode 100644 index ecd914a29c..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/includes/includeMulti.jsp +++ /dev/null @@ -1,13 +0,0 @@ - - - MULTIPLE INCLUDE ACTION JSP - - - -
-

INCLUDE MULTI

- - -
- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/invalidMarkup.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/invalidMarkup.jsp deleted file mode 100644 index 4df6452f96..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/invalidMarkup.jsp +++ /dev/null @@ -1,12 +0,0 @@ - -INVALID MARKUP JSP -<body> - <% - for (int i = 0; i < 3; ++i) { - %> - <h2>number:<%= i %></h2><p></p> - <% - } - %> -</boody> -</html> diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/invalidWrite.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/invalidWrite.jsp deleted file mode 100644 index d4506c49d8..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/invalidWrite.jsp +++ /dev/null @@ -1,8 +0,0 @@ -<html> - <head><title>RUNTIME ERROR JSP: INVALID WRITE - - <% - response.getWriter().write("hello world", 0, 2147483647); - %> - - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/nojava.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/nojava.jsp deleted file mode 100644 index 9eff4b79e0..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/nojava.jsp +++ /dev/null @@ -1,6 +0,0 @@ - - NO JAVA JSP - -

there's no java code here

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/post.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/post.jsp deleted file mode 100644 index 09de84aad4..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/post.jsp +++ /dev/null @@ -1,6 +0,0 @@ - - POST JSP - -

Hello <%= request.getParameter("name") %>!

- - diff --git a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/runtimeError.jsp b/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/runtimeError.jsp deleted file mode 100644 index de83904796..0000000000 --- a/instrumentation/jsp-2.3/src/test/resources/webapps/jsptest/runtimeError.jsp +++ /dev/null @@ -1,9 +0,0 @@ - - RUNTIME ERROR JSP: DIVISION BY ZERO - -

This will fail ...

- <% - int k = 9 / 0; - %> - - diff --git a/instrumentation/kafka-clients-0.11/kafka-clients-0.11.gradle b/instrumentation/kafka-clients-0.11/kafka-clients-0.11.gradle deleted file mode 100644 index 1cbdfce409..0000000000 --- a/instrumentation/kafka-clients-0.11/kafka-clients-0.11.gradle +++ /dev/null @@ -1,30 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.kafka" - module = "kafka-clients" - versions = "[0.11.0.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'org.apache.kafka', name: 'kafka-clients', version: '0.11.0.0' - - testLibrary group: 'org.springframework.kafka', name: 'spring-kafka', version: '1.3.3.RELEASE' - testLibrary group: 'org.springframework.kafka', name: 'spring-kafka-test', version: '1.3.3.RELEASE' - testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3' - testLibrary group: 'org.assertj', name: 'assertj-core', version: '2.9.+' - testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - - // Include latest version of kafka itself along with latest version of client libs. - // This seems to help with jar compatibility hell. - latestDepTestLibrary group: 'org.apache.kafka', name: 'kafka_2.11', version: '2.3.+' - // (Pinning to 2.3.x: 2.4.0 introduces an error when executing compileLatestDepTestGroovy) - // Caused by: java.lang.NoClassDefFoundError: org.I0Itec.zkclient.ZkClient - latestDepTestLibrary group: 'org.apache.kafka', name: 'kafka-clients', version: '2.3.+' - latestDepTestLibrary group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.2.+' - latestDepTestLibrary group: 'org.springframework.kafka', name: 'spring-kafka-test', version: '2.2.+' - latestDepTestLibrary group: 'org.assertj', name: 'assertj-core', version: '3.+' -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaClientConfiguration.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaClientConfiguration.java deleted file mode 100644 index 24f0c7b4c5..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaClientConfiguration.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import io.opentelemetry.instrumentation.api.config.Config; - -public final class KafkaClientConfiguration { - - public static boolean isPropagationEnabled() { - return Config.get().getBooleanProperty("otel.instrumentation.kafka.client-propagation", true); - } - - private KafkaClientConfiguration() {} -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaClientsInstrumentationModule.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaClientsInstrumentationModule.java deleted file mode 100644 index 68200eeb7a..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaClientsInstrumentationModule.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class KafkaClientsInstrumentationModule extends InstrumentationModule { - public KafkaClientsInstrumentationModule() { - super("kafka-clients", "kafka-clients-0.11", "kafka"); - } - - @Override - public List typeInstrumentations() { - return asList(new KafkaConsumerInstrumentation(), new KafkaProducerInstrumentation()); - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java deleted file mode 100644 index 8bcea7e4ca..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerInstrumentation.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaConsumerTracer.tracer; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.kafka.clients.consumer.ConsumerRecord; - -public class KafkaConsumerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.kafka.clients.consumer.ConsumerRecords"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(isPublic()) - .and(named("records")) - .and(takesArgument(0, String.class)) - .and(returns(Iterable.class)), - KafkaConsumerInstrumentation.class.getName() + "$IterableAdvice"); - transformers.put( - isMethod() - .and(isPublic()) - .and(named("records")) - .and(takesArgument(0, named("org.apache.kafka.common.TopicPartition"))) - .and(returns(List.class)), - KafkaConsumerInstrumentation.class.getName() + "$ListAdvice"); - transformers.put( - isMethod() - .and(isPublic()) - .and(named("iterator")) - .and(takesArguments(0)) - .and(returns(Iterator.class)), - KafkaConsumerInstrumentation.class.getName() + "$IteratorAdvice"); - return transformers; - } - - public static class IterableAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void wrap( - @Advice.Return(readOnly = false) Iterable> iterable) { - if (iterable != null) { - iterable = new TracingIterable(iterable, tracer()); - } - } - } - - public static class ListAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void wrap(@Advice.Return(readOnly = false) List> iterable) { - if (iterable != null) { - iterable = new TracingList(iterable, tracer()); - } - } - } - - public static class IteratorAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void wrap( - @Advice.Return(readOnly = false) Iterator> iterator) { - if (iterator != null) { - iterator = new TracingIterator(iterator, tracer()); - } - } - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerTracer.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerTracer.java deleted file mode 100644 index 4e6c7c3b72..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaConsumerTracer.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER; -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.TextMapExtractAdapter.GETTER; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.util.concurrent.TimeUnit; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.common.record.TimestampType; - -public class KafkaConsumerTracer extends BaseTracer { - private static final KafkaConsumerTracer TRACER = new KafkaConsumerTracer(); - - public static KafkaConsumerTracer tracer() { - return TRACER; - } - - public Span startSpan(ConsumerRecord record) { - long now = System.currentTimeMillis(); - - Span span = - tracer - .spanBuilder(spanNameOnConsume(record)) - .setSpanKind(CONSUMER) - .setParent(extractParent(record)) - .setStartTimestamp(now, TimeUnit.MILLISECONDS) - .setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "kafka") - .setAttribute(SemanticAttributes.MESSAGING_DESTINATION, record.topic()) - .setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "topic") - .setAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .setAttribute( - SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, - (long) record.serializedValueSize()) - .startSpan(); - - onConsume(span, now, record); - return span; - } - - private Context extractParent(ConsumerRecord record) { - if (KafkaClientConfiguration.isPropagationEnabled()) { - return extract(record.headers(), GETTER); - } else { - return Context.current(); - } - } - - public String spanNameOnConsume(ConsumerRecord record) { - return record.topic() + " process"; - } - - public void onConsume(Span span, long startTimeMillis, ConsumerRecord record) { - // TODO should we set topic + offset as messaging.message_id? - span.setAttribute("partition", record.partition()); - span.setAttribute("offset", record.offset()); - - if (record.value() == null) { - span.setAttribute("tombstone", true); - } - - // don't record a duration if the message was sent from an old Kafka client - if (record.timestampType() != TimestampType.NO_TIMESTAMP_TYPE) { - long produceTime = record.timestamp(); - // this attribute shows how much time elapsed between the producer and the consumer of this - // message, which can be helpful for identifying queue bottlenecks - span.setAttribute("record.queue_time_ms", Math.max(0L, startTimeMillis - produceTime)); - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.kafka-clients"; - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java deleted file mode 100644 index 5421864032..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerInstrumentation.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaProducerTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.TextMapInjectAdapter.SETTER; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.kafka.clients.ApiVersions; -import org.apache.kafka.clients.producer.Callback; -import org.apache.kafka.clients.producer.ProducerRecord; - -public class KafkaProducerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.kafka.clients.producer.KafkaProducer"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(named("send")) - .and(takesArgument(0, named("org.apache.kafka.clients.producer.ProducerRecord"))) - .and(takesArgument(1, named("org.apache.kafka.clients.producer.Callback"))), - KafkaProducerInstrumentation.class.getName() + "$ProducerAdvice"); - } - - public static class ProducerAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.FieldValue("apiVersions") ApiVersions apiVersions, - @Advice.Argument(value = 0, readOnly = false) ProducerRecord record, - @Advice.Argument(value = 1, readOnly = false) Callback callback, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - Context parent = Java8BytecodeBridge.currentContext(); - - span = tracer().startProducerSpan(record); - Context newContext = parent.with(span); - - callback = new ProducerCallback(callback, parent, span); - - if (tracer().shouldPropagate(apiVersions)) { - try { - Java8BytecodeBridge.getGlobalPropagators() - .getTextMapPropagator() - .inject(newContext, record.headers(), SETTER); - } catch (IllegalStateException e) { - // headers must be read-only from reused record. try again with new one. - record = - new ProducerRecord<>( - record.topic(), - record.partition(), - record.timestamp(), - record.key(), - record.value(), - record.headers()); - - Java8BytecodeBridge.getGlobalPropagators() - .getTextMapPropagator() - .inject(newContext, record.headers(), SETTER); - } - } - - scope = newContext.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - // span finished by ProducerCallback - } - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerTracer.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerTracer.java deleted file mode 100644 index cd0ff76805..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/KafkaProducerTracer.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import org.apache.kafka.clients.ApiVersions; -import org.apache.kafka.clients.producer.ProducerRecord; -import org.apache.kafka.common.record.RecordBatch; - -public class KafkaProducerTracer extends BaseTracer { - private static final KafkaProducerTracer TRACER = new KafkaProducerTracer(); - - public static KafkaProducerTracer tracer() { - return TRACER; - } - - public Span startProducerSpan(ProducerRecord record) { - Span span = startSpan(spanNameOnProduce(record), PRODUCER); - onProduce(span, record); - return span; - } - - // Do not inject headers for batch versions below 2 - // This is how similar check is being done in Kafka client itself: - // https://github.com/apache/kafka/blob/05fcfde8f69b0349216553f711fdfc3f0259c601/clients/src/main/java/org/apache/kafka/common/record/MemoryRecordsBuilder.java#L411-L412 - // Also, do not inject headers if specified by JVM option or environment variable - // This can help in mixed client environments where clients < 0.11 that do not support - // headers attempt to read messages that were produced by clients > 0.11 and the magic - // value of the broker(s) is >= 2 - public boolean shouldPropagate(ApiVersions apiVersions) { - return apiVersions.maxUsableProduceMagic() >= RecordBatch.MAGIC_VALUE_V2 - && KafkaClientConfiguration.isPropagationEnabled(); - } - - public String spanNameOnProduce(ProducerRecord record) { - return record.topic() + " send"; - } - - public void onProduce(Span span, ProducerRecord record) { - span.setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "kafka"); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "topic"); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, record.topic()); - - Integer partition = record.partition(); - if (partition != null) { - span.setAttribute("partition", partition); - } - if (record.value() == null) { - span.setAttribute("tombstone", true); - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.kafka-clients"; - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java deleted file mode 100644 index 9035898e7e..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/ProducerCallback.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import static io.opentelemetry.javaagent.instrumentation.kafkaclients.KafkaProducerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import org.apache.kafka.clients.producer.Callback; -import org.apache.kafka.clients.producer.RecordMetadata; - -public class ProducerCallback implements Callback { - private final Callback callback; - private final Context parent; - private final Span span; - - public ProducerCallback(Callback callback, Context parent, Span span) { - this.callback = callback; - this.parent = parent; - this.span = span; - } - - @Override - public void onCompletion(RecordMetadata metadata, Exception exception) { - if (exception != null) { - tracer().endExceptionally(span, exception); - } else { - tracer().end(span); - } - - if (callback != null) { - if (parent != null) { - try (Scope ignored = parent.makeCurrent()) { - callback.onCompletion(metadata, exception); - } - } else { - callback.onCompletion(metadata, exception); - } - } - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TextMapExtractAdapter.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TextMapExtractAdapter.java deleted file mode 100644 index 94344549db..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TextMapExtractAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.nio.charset.StandardCharsets; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.apache.kafka.common.header.Header; -import org.apache.kafka.common.header.Headers; - -public class TextMapExtractAdapter implements TextMapPropagator.Getter { - - public static final TextMapExtractAdapter GETTER = new TextMapExtractAdapter(); - - @Override - public Iterable keys(Headers headers) { - return StreamSupport.stream(headers.spliterator(), false) - .map(Header::key) - .collect(Collectors.toList()); - } - - @Override - public String get(Headers headers, String key) { - Header header = headers.lastHeader(key); - if (header == null) { - return null; - } - byte[] value = header.value(); - if (value == null) { - return null; - } - return new String(value, StandardCharsets.UTF_8); - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TextMapInjectAdapter.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TextMapInjectAdapter.java deleted file mode 100644 index 8393b6d032..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TextMapInjectAdapter.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.nio.charset.StandardCharsets; -import org.apache.kafka.common.header.Headers; - -public class TextMapInjectAdapter implements TextMapPropagator.Setter { - - public static final TextMapInjectAdapter SETTER = new TextMapInjectAdapter(); - - @Override - public void set(Headers headers, String key, String value) { - headers.remove(key).add(key, value.getBytes(StandardCharsets.UTF_8)); - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java deleted file mode 100644 index e181af7d6c..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterable.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import java.util.Iterator; -import org.apache.kafka.clients.consumer.ConsumerRecord; - -public class TracingIterable implements Iterable> { - private final Iterable> delegate; - private final KafkaConsumerTracer tracer; - private boolean firstIterator = true; - - public TracingIterable(Iterable> delegate, KafkaConsumerTracer tracer) { - this.delegate = delegate; - this.tracer = tracer; - } - - @Override - public Iterator> iterator() { - Iterator> it; - // We should only return one iterator with tracing. - // However, this is not thread-safe, but usually the first (hopefully only) traversal of - // ConsumerRecords is performed in the same thread that called poll() - if (firstIterator) { - it = new TracingIterator(delegate.iterator(), tracer); - firstIterator = false; - } else { - it = delegate.iterator(); - } - - return it; - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java deleted file mode 100644 index 4300ea093f..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingIterator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import java.util.Iterator; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TracingIterator implements Iterator> { - - private static final Logger log = LoggerFactory.getLogger(TracingIterator.class); - - private final Iterator> delegateIterator; - private final KafkaConsumerTracer tracer; - private final boolean propagationEnabled; - - /** - * Note: this may potentially create problems if this iterator is used from different threads. But - * at the moment we cannot do much about this. - */ - private SpanWithScope currentSpanWithScope; - - public TracingIterator( - Iterator> delegateIterator, KafkaConsumerTracer tracer) { - this.delegateIterator = delegateIterator; - this.tracer = tracer; - this.propagationEnabled = KafkaClientConfiguration.isPropagationEnabled(); - } - - @Override - public boolean hasNext() { - if (currentSpanWithScope != null) { - tracer.end(currentSpanWithScope.getSpan()); - currentSpanWithScope.closeScope(); - currentSpanWithScope = null; - } - return delegateIterator.hasNext(); - } - - @Override - public ConsumerRecord next() { - if (currentSpanWithScope != null) { - // in case they didn't call hasNext()... - tracer.end(currentSpanWithScope.getSpan()); - currentSpanWithScope.closeScope(); - currentSpanWithScope = null; - } - - ConsumerRecord next = delegateIterator.next(); - - try { - if (next != null) { - Span span = tracer.startSpan(next); - - currentSpanWithScope = new SpanWithScope(span, span.makeCurrent()); - } - } catch (Exception e) { - log.debug("Error during decoration", e); - } - return next; - } - - @Override - public void remove() { - delegateIterator.remove(); - } -} diff --git a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingList.java b/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingList.java deleted file mode 100644 index 6b0b4154f2..0000000000 --- a/instrumentation/kafka-clients-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/TracingList.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkaclients; - -import java.util.Collection; -import java.util.List; -import java.util.ListIterator; -import org.apache.kafka.clients.consumer.ConsumerRecord; - -public class TracingList extends TracingIterable implements List> { - private final List> delegate; - - public TracingList(List> delegate, KafkaConsumerTracer tracer) { - super(delegate, tracer); - this.delegate = delegate; - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return delegate.contains(o); - } - - @Override - public Object[] toArray() { - return delegate.toArray(); - } - - @Override - public T[] toArray(T[] a) { - return delegate.toArray(a); - } - - @Override - public boolean add(ConsumerRecord consumerRecord) { - return delegate.add(consumerRecord); - } - - @Override - public void add(int index, ConsumerRecord element) { - delegate.add(index, element); - } - - @Override - public boolean remove(Object o) { - return delegate.remove(o); - } - - @Override - public ConsumerRecord remove(int index) { - return delegate.remove(index); - } - - @Override - public boolean containsAll(Collection c) { - return delegate.containsAll(c); - } - - @Override - public boolean addAll(Collection> c) { - return delegate.addAll(c); - } - - @Override - public boolean addAll(int index, Collection> c) { - return delegate.addAll(index, c); - } - - @Override - public boolean removeAll(Collection c) { - return delegate.removeAll(c); - } - - @Override - public boolean retainAll(Collection c) { - return delegate.retainAll(c); - } - - @Override - public void clear() { - delegate.clear(); - } - - @Override - public ConsumerRecord get(int index) { - // TODO: should this be instrumented as well? - return delegate.get(index); - } - - @Override - public ConsumerRecord set(int index, ConsumerRecord element) { - return delegate.set(index, element); - } - - @Override - public int indexOf(Object o) { - return delegate.indexOf(o); - } - - @Override - public int lastIndexOf(Object o) { - return delegate.lastIndexOf(o); - } - - @Override - public ListIterator> listIterator() { - // TODO: the API for ListIterator is not really good to instrument it in context of Kafka - // Consumer so we will not do that for now - return delegate.listIterator(); - } - - @Override - public ListIterator> listIterator(int index) { - // TODO: the API for ListIterator is not really good to instrument it in context of Kafka - // Consumer so we will not do that for now - return delegate.listIterator(index); - } - - @Override - public List> subList(int fromIndex, int toIndex) { - // TODO: the API for subList is not really good to instrument it in context of Kafka - // Consumer so we will not do that for now - // Kafka is essentially a sequential commit log. We should only enable tracing when traversing - // sequentially with an iterator - return delegate.subList(fromIndex, toIndex); - } -} diff --git a/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy b/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy deleted file mode 100644 index 36629e6436..0000000000 --- a/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER -import static io.opentelemetry.instrumentation.test.utils.ConfigUtils.setConfig -import static io.opentelemetry.instrumentation.test.utils.ConfigUtils.updateConfig -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.api.config.Config -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.LinkedBlockingQueue -import java.util.concurrent.TimeUnit -import org.apache.kafka.clients.consumer.ConsumerConfig -import org.apache.kafka.clients.consumer.ConsumerRecord -import org.apache.kafka.clients.consumer.KafkaConsumer -import org.apache.kafka.clients.producer.KafkaProducer -import org.apache.kafka.clients.producer.Producer -import org.apache.kafka.clients.producer.ProducerRecord -import org.apache.kafka.common.TopicPartition -import org.apache.kafka.common.serialization.StringSerializer -import org.junit.Rule -import org.springframework.kafka.core.DefaultKafkaConsumerFactory -import org.springframework.kafka.core.DefaultKafkaProducerFactory -import org.springframework.kafka.core.KafkaTemplate -import org.springframework.kafka.listener.KafkaMessageListenerContainer -import org.springframework.kafka.listener.MessageListener -import org.springframework.kafka.test.rule.KafkaEmbedded -import org.springframework.kafka.test.utils.ContainerTestUtils -import org.springframework.kafka.test.utils.KafkaTestUtils -import spock.lang.Unroll - -class KafkaClientTest extends AgentTestRunner { - static final SHARED_TOPIC = "shared.topic" - - @Rule - KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, SHARED_TOPIC) - - def "test kafka produce and consume"() { - setup: - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - Producer producer = new KafkaProducer<>(senderProps, new StringSerializer(), new StringSerializer()) - - // set up the Kafka consumer properties - def consumerProperties = KafkaTestUtils.consumerProps("sender", "false", embeddedKafka) - - // create a Kafka consumer factory - def consumerFactory = new DefaultKafkaConsumerFactory(consumerProperties) - - // set the topic that needs to be consumed - def containerProperties = containerProperties() - - // create a Kafka MessageListenerContainer - def container = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties) - - // create a thread safe queue to store the received message - def records = new LinkedBlockingQueue>() - - // setup a Kafka message listener - container.setupMessageListener(new MessageListener() { - @Override - void onMessage(ConsumerRecord record) { - TEST_WRITER.waitForTraces(1) // ensure consistent ordering of traces - records.add(record) - } - }) - - // start the container and underlying message listener - container.start() - - // wait until the container has the required number of assigned partitions - ContainerTestUtils.waitForAssignment(container, embeddedKafka.getPartitionsPerTopic()) - - when: - String greeting = "Hello Spring Kafka Sender!" - runUnderTrace("parent") { - producer.send(new ProducerRecord(SHARED_TOPIC, greeting)) { meta, ex -> - if (ex == null) { - runUnderTrace("producer callback") {} - } else { - runUnderTrace("producer exception: " + ex) {} - } - } - } - - then: - // check that the message was received - def received = records.poll(5, TimeUnit.SECONDS) - received.value() == greeting - received.key() == null - - assertTraces(1) { - trace(0, 4) { - basicSpan(it, 0, "parent") - span(1) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - span(2) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - childOf span(1) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - basicSpan(it, 3, "producer callback", span(0)) - } - } - - cleanup: - producer.close() - container?.stop() - } - - def "test spring kafka template produce and consume"() { - setup: - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - def producerFactory = new DefaultKafkaProducerFactory(senderProps) - def kafkaTemplate = new KafkaTemplate(producerFactory) - - // set up the Kafka consumer properties - def consumerProperties = KafkaTestUtils.consumerProps("sender", "false", embeddedKafka) - - // create a Kafka consumer factory - def consumerFactory = new DefaultKafkaConsumerFactory(consumerProperties) - - // set the topic that needs to be consumed - def containerProperties = containerProperties() - - // create a Kafka MessageListenerContainer - def container = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties) - - // create a thread safe queue to store the received message - def records = new LinkedBlockingQueue>() - - // setup a Kafka message listener - container.setupMessageListener(new MessageListener() { - @Override - void onMessage(ConsumerRecord record) { - records.add(record) - } - }) - - // start the container and underlying message listener - container.start() - - // wait until the container has the required number of assigned partitions - ContainerTestUtils.waitForAssignment(container, embeddedKafka.getPartitionsPerTopic()) - - when: - String greeting = "Hello Spring Kafka Sender!" - runUnderTrace("parent") { - kafkaTemplate.send(SHARED_TOPIC, greeting).addCallback({ - runUnderTrace("producer callback") {} - }, { ex -> - runUnderTrace("producer exception: " + ex) {} - }) - } - - then: - // check that the message was received - def received = records.poll(5, TimeUnit.SECONDS) - received.value() == greeting - received.key() == null - - assertTraces(1) { - trace(0, 4) { - basicSpan(it, 0, "parent") - span(1) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - span(2) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - childOf span(1) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - basicSpan(it, 3, "producer callback", span(0)) - } - } - - cleanup: - producerFactory.stop() - container?.stop() - } - - def "test pass through tombstone"() { - setup: - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - def producerFactory = new DefaultKafkaProducerFactory(senderProps) - def kafkaTemplate = new KafkaTemplate(producerFactory) - - // set up the Kafka consumer properties - def consumerProperties = KafkaTestUtils.consumerProps("sender", "false", embeddedKafka) - - // create a Kafka consumer factory - def consumerFactory = new DefaultKafkaConsumerFactory(consumerProperties) - - // set the topic that needs to be consumed - def containerProperties = containerProperties() - - // create a Kafka MessageListenerContainer - def container = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties) - - // create a thread safe queue to store the received message - def records = new LinkedBlockingQueue>() - - // setup a Kafka message listener - container.setupMessageListener(new MessageListener() { - @Override - void onMessage(ConsumerRecord record) { - records.add(record) - } - }) - - // start the container and underlying message listener - container.start() - - // wait until the container has the required number of assigned partitions - ContainerTestUtils.waitForAssignment(container, embeddedKafka.getPartitionsPerTopic()) - - when: - kafkaTemplate.send(SHARED_TOPIC, null) - - then: - // check that the message was received - def received = records.poll(5, TimeUnit.SECONDS) - received.value() == null - received.key() == null - - assertTraces(1) { - trace(0, 2) { - // PRODUCER span 0 - span(0) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "tombstone" true - } - } - // CONSUMER span 0 - span(1) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - "tombstone" true - } - } - } - } - - cleanup: - producerFactory.stop() - container?.stop() - } - - def "test records(TopicPartition) kafka consume"() { - setup: - - // set up the Kafka consumer properties - def kafkaPartition = 0 - def consumerProperties = KafkaTestUtils.consumerProps("sender", "false", embeddedKafka) - consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest") - def consumer = new KafkaConsumer(consumerProperties) - - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - def producer = new KafkaProducer(senderProps) - - consumer.assign(Arrays.asList(new TopicPartition(SHARED_TOPIC, kafkaPartition))) - - when: - def greeting = "Hello from MockConsumer!" - producer.send(new ProducerRecord(SHARED_TOPIC, kafkaPartition, null, greeting)) - - then: - TEST_WRITER.waitForTraces(1) - def records = new LinkedBlockingQueue>() - def pollResult = KafkaTestUtils.getRecords(consumer) - - def recs = pollResult.records(new TopicPartition(SHARED_TOPIC, kafkaPartition)).iterator() - - def first = null - if (recs.hasNext()) { - first = recs.next() - } - - then: - recs.hasNext() == false - first.value() == greeting - first.key() == null - - assertTraces(1) { - trace(0, 2) { - span(0) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "partition" { it >= 0 } - } - } - span(1) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - } - } - - cleanup: - consumer.close() - producer.close() - } - - @Unroll - def "test kafka client header propagation manual config"() { - setup: - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - def producerFactory = new DefaultKafkaProducerFactory(senderProps) - def kafkaTemplate = new KafkaTemplate(producerFactory) - - // set up the Kafka consumer properties - def consumerProperties = KafkaTestUtils.consumerProps("sender", "false", embeddedKafka) - - // create a Kafka consumer factory - def consumerFactory = new DefaultKafkaConsumerFactory(consumerProperties) - - // set the topic that needs to be consumed - def containerProperties = containerProperties() - - // create a Kafka MessageListenerContainer - def container = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties) - - // create a thread safe queue to store the received message - def records = new LinkedBlockingQueue>() - - // setup a Kafka message listener - container.setupMessageListener(new MessageListener() { - @Override - void onMessage(ConsumerRecord record) { - records.add(record) - } - }) - - // start the container and underlying message listener - container.start() - - // wait until the container has the required number of assigned partitions - ContainerTestUtils.waitForAssignment(container, embeddedKafka.getPartitionsPerTopic()) - - when: - String message = "Testing without headers" - def previousConfig = setPropagation(propagationEnabled) - kafkaTemplate.send(SHARED_TOPIC, message) - setConfig(previousConfig) - - then: - // check that the message was received - def received = records.poll(5, TimeUnit.SECONDS) - - received.headers().iterator().hasNext() == propagationEnabled - - cleanup: - producerFactory.stop() - container?.stop() - - where: - propagationEnabled << [false, true] - } - - def "should not read remote context when consuming messages if propagation is disabled"() { - setup: - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - def producerFactory = new DefaultKafkaProducerFactory(senderProps) - def kafkaTemplate = new KafkaTemplate(producerFactory) - - when: "send message" - String message = "Testing without headers" - kafkaTemplate.send(SHARED_TOPIC, message) - - then: "producer span is created" - assertTraces(1) { - trace(0, 1) { - span(0) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - } - } - - when: "read message with context propagation" - // create a thread safe queue to store the received message - def records = new LinkedBlockingQueue>() - KafkaMessageListenerContainer container = startConsumer("consumer-with-propagation", records) - - then: "consumer span is created and is a child of the producer" - // check that the message was received - records.poll(5, TimeUnit.SECONDS) != null - - assertTraces(1) { - trace(0, 2) { - span(0) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - span(1) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - } - } - container.stop() - - when: "read message without context propagation" - def previousConfig = setPropagation(false) - records.clear() - container = startConsumer("consumer-without-propagation", records) - - then: "independent consumer span is created" - // check that the message was received - records.poll(5, TimeUnit.SECONDS) != null - - assertTraces(2) { - trace(0, 2) { - span(0) { - name SHARED_TOPIC + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - span(1) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - } - trace(1, 1) { - span(0) { - name SHARED_TOPIC + " process" - kind CONSUMER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" SHARED_TOPIC - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - } - - } - - cleanup: - producerFactory.stop() - container?.stop() - setConfig(previousConfig) - } - - protected KafkaMessageListenerContainer startConsumer(String groupId, records) { - // set up the Kafka consumer properties - Map consumerProperties = KafkaTestUtils.consumerProps(groupId, "false", embeddedKafka) - consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest") - - // create a Kafka consumer factory - def consumerFactory = new DefaultKafkaConsumerFactory(consumerProperties) - - // set the topic that needs to be consumed - def containerProperties = containerProperties() - - // create a Kafka MessageListenerContainer - def container = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties) - - // setup a Kafka message listener - container.setupMessageListener(new MessageListener() { - @Override - void onMessage(ConsumerRecord record) { - records.add(record) - } - }) - - // start the container and underlying message listener - container.start() - - // wait until the container has the required number of assigned partitions - ContainerTestUtils.waitForAssignment(container, embeddedKafka.getPartitionsPerTopic()) - container - } - - - def containerProperties() { - try { - // Different class names for test and latestDepTest. - return Class.forName("org.springframework.kafka.listener.config.ContainerProperties").newInstance(SHARED_TOPIC) - } catch (ClassNotFoundException | NoClassDefFoundError e) { - return Class.forName("org.springframework.kafka.listener.ContainerProperties").newInstance(SHARED_TOPIC) - } - } - - private static Config setPropagation(boolean propagationEnabled) { - return updateConfig { - it.setProperty("otel.instrumentation.kafka.client-propagation", Boolean.toString(propagationEnabled)) - } - } -} diff --git a/instrumentation/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsTest.groovy b/instrumentation/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsTest.groovy index 104b7d3536..7dd750ddbd 100644 --- a/instrumentation/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsTest.groovy +++ b/instrumentation/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsTest.groovy @@ -6,12 +6,12 @@ import static io.opentelemetry.api.trace.Span.Kind.CONSUMER import static io.opentelemetry.api.trace.Span.Kind.PRODUCER -import io.opentelemetry.context.Context -import io.opentelemetry.context.propagation.TextMapPropagator -import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.api.trace.propagation.HttpTraceContext +import io.opentelemetry.context.Context +import io.opentelemetry.context.propagation.TextMapPropagator +import io.opentelemetry.instrumentation.test.AgentTestRunner import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit import org.apache.kafka.clients.consumer.ConsumerRecord diff --git a/instrumentation/kafka-streams-0.11/kafka-streams-0.11.gradle b/instrumentation/kafka-streams-0.11/kafka-streams-0.11.gradle deleted file mode 100644 index 3dea901fb5..0000000000 --- a/instrumentation/kafka-streams-0.11/kafka-streams-0.11.gradle +++ /dev/null @@ -1,35 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.kafka" - module = "kafka-streams" - versions = "[0.11.0.0,)" - } -} - -dependencies { - library group: 'org.apache.kafka', name: 'kafka-streams', version: '0.11.0.0' - - // Include kafka-clients instrumentation for tests. - testImplementation project(':instrumentation:kafka-clients-0.11') - - testLibrary group: 'org.apache.kafka', name: 'kafka-clients', version: '0.11.0.0' - testLibrary group: 'org.springframework.kafka', name: 'spring-kafka', version: '1.3.3.RELEASE' - testLibrary group: 'org.springframework.kafka', name: 'spring-kafka-test', version: '1.3.3.RELEASE' - testImplementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3' - testLibrary group: 'org.assertj', name: 'assertj-core', version: '2.9.+' - testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.6.0' - - - // Include latest version of kafka itself along with latest version of client libs. - // This seems to help with jar compatibility hell. - latestDepTestLibrary group: 'org.apache.kafka', name: 'kafka_2.11', version: '2.3.+' - // (Pinning to 2.3.x: 2.4.0 introduces an error when executing compileLatestDepTestGroovy) - // Caused by: java.lang.NoClassDefFoundError: org.I0Itec.zkclient.ZkClient - latestDepTestLibrary group: 'org.apache.kafka', name: 'kafka-clients', version: '2.3.+' - latestDepTestLibrary group: 'org.apache.kafka', name: 'kafka-streams', version: '2.3.+' - latestDepTestLibrary group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.2.+' - latestDepTestLibrary group: 'org.springframework.kafka', name: 'spring-kafka-test', version: '2.2.+' - latestDepTestLibrary group: 'org.assertj', name: 'assertj-core', version: '3.+' -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsInstrumentationModule.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsInstrumentationModule.java deleted file mode 100644 index cb395a95bc..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsInstrumentationModule.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class KafkaStreamsInstrumentationModule extends InstrumentationModule { - public KafkaStreamsInstrumentationModule() { - super("kafka-streams", "kafka-streams-0.11", "kafka"); - } - - @Override - public List typeInstrumentations() { - return asList( - new KafkaStreamsSourceNodeRecordDeserializerInstrumentation(), - new StreamTaskStartInstrumentation(), - new StreamTaskStopInstrumentation()); - } -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSourceNodeRecordDeserializerInstrumentation.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSourceNodeRecordDeserializerInstrumentation.java deleted file mode 100644 index 36d2ad31b5..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSourceNodeRecordDeserializerInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.common.record.TimestampType; - -// This is necessary because SourceNodeRecordDeserializer drops the headers. :-( -public class KafkaStreamsSourceNodeRecordDeserializerInstrumentation - implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.kafka.streams.processor.internals.SourceNodeRecordDeserializer"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(named("deserialize")) - .and(takesArgument(0, named("org.apache.kafka.clients.consumer.ConsumerRecord"))) - .and(returns(named("org.apache.kafka.clients.consumer.ConsumerRecord"))), - KafkaStreamsSourceNodeRecordDeserializerInstrumentation.class.getName() - + "$SaveHeadersAdvice"); - } - - public static class SaveHeadersAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void saveHeaders( - @Advice.Argument(0) ConsumerRecord incoming, - @Advice.Return(readOnly = false) ConsumerRecord result) { - result = - new ConsumerRecord<>( - result.topic(), - result.partition(), - result.offset(), - result.timestamp(), - TimestampType.CREATE_TIME, - result.checksum(), - result.serializedKeySize(), - result.serializedValueSize(), - result.key(), - result.value(), - incoming.headers()); - } - } -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsTracer.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsTracer.java deleted file mode 100644 index 03db415a8f..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsTracer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import static io.opentelemetry.javaagent.instrumentation.kafkastreams.TextMapExtractAdapter.GETTER; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import org.apache.kafka.streams.processor.internals.StampedRecord; - -public class KafkaStreamsTracer extends BaseTracer { - private static final KafkaStreamsTracer TRACER = new KafkaStreamsTracer(); - - public static KafkaStreamsTracer tracer() { - return TRACER; - } - - public Span startSpan(StampedRecord record) { - Span span = - tracer - .spanBuilder(spanNameForConsume(record)) - .setSpanKind(Kind.CONSUMER) - .setParent(extract(record.value.headers(), GETTER)) - .setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "kafka") - .setAttribute(SemanticAttributes.MESSAGING_DESTINATION, record.topic()) - .setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "topic") - .setAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .startSpan(); - onConsume(span, record); - return span; - } - - public String spanNameForConsume(StampedRecord record) { - if (record == null) { - return null; - } - return record.topic() + " process"; - } - - public void onConsume(Span span, StampedRecord record) { - if (record != null) { - span.setAttribute("partition", record.partition()); - span.setAttribute("offset", record.offset()); - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.kafka-streams"; - } -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/SpanScopeHolder.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/SpanScopeHolder.java deleted file mode 100644 index 9aaa53976a..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/SpanScopeHolder.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; - -public class SpanScopeHolder { - public static final ThreadLocal HOLDER = new ThreadLocal<>(); - - private SpanWithScope spanWithScope; - - public SpanWithScope getSpanWithScope() { - return spanWithScope; - } - - public void setSpanWithScope(SpanWithScope spanWithScope) { - this.spanWithScope = spanWithScope; - } -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskStartInstrumentation.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskStartInstrumentation.java deleted file mode 100644 index aa5036c380..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskStartInstrumentation.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import static io.opentelemetry.javaagent.instrumentation.kafkastreams.KafkaStreamsTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.kafkastreams.SpanScopeHolder.HOLDER; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPackagePrivate; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.kafka.streams.processor.internals.StampedRecord; - -public class StreamTaskStartInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.kafka.streams.processor.internals.PartitionGroup"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPackagePrivate()) - .and(named("nextRecord")) - .and(returns(named("org.apache.kafka.streams.processor.internals.StampedRecord"))), - StreamTaskStartInstrumentation.class.getName() + "$StartSpanAdvice"); - } - - public static class StartSpanAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit(@Advice.Return StampedRecord record) { - if (record == null) { - return; - } - - SpanScopeHolder holder = HOLDER.get(); - if (holder == null) { - // somehow nextRecord() was called outside of process() - return; - } - - Span span = tracer().startSpan(record); - - holder.setSpanWithScope(new SpanWithScope(span, span.makeCurrent())); - } - } -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskStopInstrumentation.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskStopInstrumentation.java deleted file mode 100644 index 110079c8dd..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/StreamTaskStopInstrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import static io.opentelemetry.javaagent.instrumentation.kafkastreams.KafkaStreamsTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.kafkastreams.SpanScopeHolder.HOLDER; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class StreamTaskStopInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.kafka.streams.processor.internals.StreamTask"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("process")).and(takesArguments(0)), - StreamTaskStopInstrumentation.class.getName() + "$StopSpanAdvice"); - } - - public static class StopSpanAdvice { - - @Advice.OnMethodEnter - public static SpanScopeHolder onEnter() { - SpanScopeHolder holder = new SpanScopeHolder(); - HOLDER.set(holder); - return holder; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Enter SpanScopeHolder holder, @Advice.Thrown Throwable throwable) { - HOLDER.remove(); - SpanWithScope spanWithScope = holder.getSpanWithScope(); - if (spanWithScope != null) { - spanWithScope.closeScope(); - - Span span = spanWithScope.getSpan(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } - } -} diff --git a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/TextMapExtractAdapter.java b/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/TextMapExtractAdapter.java deleted file mode 100644 index 6f13bb5197..0000000000 --- a/instrumentation/kafka-streams-0.11/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/TextMapExtractAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kafkastreams; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.nio.charset.StandardCharsets; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.apache.kafka.common.header.Header; -import org.apache.kafka.common.header.Headers; - -public class TextMapExtractAdapter implements TextMapPropagator.Getter { - - public static final TextMapExtractAdapter GETTER = new TextMapExtractAdapter(); - - @Override - public Iterable keys(Headers headers) { - return StreamSupport.stream(headers.spliterator(), false) - .map(Header::key) - .collect(Collectors.toList()); - } - - @Override - public String get(Headers headers, String key) { - Header header = headers.lastHeader(key); - if (header == null) { - return null; - } - byte[] value = header.value(); - if (value == null) { - return null; - } - return new String(value, StandardCharsets.UTF_8); - } -} diff --git a/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy b/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy deleted file mode 100644 index 7dd750ddbd..0000000000 --- a/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.api.trace.propagation.HttpTraceContext -import io.opentelemetry.context.Context -import io.opentelemetry.context.propagation.TextMapPropagator -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.LinkedBlockingQueue -import java.util.concurrent.TimeUnit -import org.apache.kafka.clients.consumer.ConsumerRecord -import org.apache.kafka.common.serialization.Serdes -import org.apache.kafka.streams.KafkaStreams -import org.apache.kafka.streams.StreamsConfig -import org.apache.kafka.streams.kstream.KStream -import org.apache.kafka.streams.kstream.ValueMapper -import org.junit.ClassRule -import org.springframework.kafka.core.DefaultKafkaConsumerFactory -import org.springframework.kafka.core.DefaultKafkaProducerFactory -import org.springframework.kafka.core.KafkaTemplate -import org.springframework.kafka.listener.KafkaMessageListenerContainer -import org.springframework.kafka.listener.MessageListener -import org.springframework.kafka.test.rule.KafkaEmbedded -import org.springframework.kafka.test.utils.ContainerTestUtils -import org.springframework.kafka.test.utils.KafkaTestUtils -import spock.lang.Shared - -class KafkaStreamsTest extends AgentTestRunner { - static final STREAM_PENDING = "test.pending" - static final STREAM_PROCESSED = "test.processed" - - @Shared - @ClassRule - KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, STREAM_PENDING, STREAM_PROCESSED) - - def "test kafka produce and consume with streams in-between"() { - setup: - def config = new Properties() - def senderProps = KafkaTestUtils.senderProps(embeddedKafka.getBrokersAsString()) - config.putAll(senderProps) - config.put(StreamsConfig.APPLICATION_ID_CONFIG, "test-application") - config.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName()) - config.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName()) - - // CONFIGURE CONSUMER - def consumerFactory = new DefaultKafkaConsumerFactory(KafkaTestUtils.consumerProps("sender", "false", embeddedKafka)) - - def containerProperties - try { - // Different class names for test and latestDepTest. - containerProperties = Class.forName("org.springframework.kafka.listener.config.ContainerProperties").newInstance(STREAM_PROCESSED) - } catch (ClassNotFoundException | NoClassDefFoundError e) { - containerProperties = Class.forName("org.springframework.kafka.listener.ContainerProperties").newInstance(STREAM_PROCESSED) - } - def consumerContainer = new KafkaMessageListenerContainer<>(consumerFactory, containerProperties) - - // create a thread safe queue to store the processed message - def records = new LinkedBlockingQueue>() - - // setup a Kafka message listener - consumerContainer.setupMessageListener(new MessageListener() { - @Override - void onMessage(ConsumerRecord record) { - Span.current().setAttribute("testing", 123) - records.add(record) - } - }) - - // start the container and underlying message listener - consumerContainer.start() - - // wait until the container has the required number of assigned partitions - ContainerTestUtils.waitForAssignment(consumerContainer, embeddedKafka.getPartitionsPerTopic()) - - // CONFIGURE PROCESSOR - def builder - try { - // Different class names for test and latestDepTest. - builder = Class.forName("org.apache.kafka.streams.kstream.KStreamBuilder").newInstance() - } catch (ClassNotFoundException | NoClassDefFoundError e) { - builder = Class.forName("org.apache.kafka.streams.StreamsBuilder").newInstance() - } - KStream textLines = builder.stream(STREAM_PENDING) - def values = textLines - .mapValues(new ValueMapper() { - @Override - String apply(String textLine) { - Span.current().setAttribute("asdf", "testing") - return textLine.toLowerCase() - } - }) - - KafkaStreams streams - try { - // Different api for test and latestDepTest. - values.to(Serdes.String(), Serdes.String(), STREAM_PROCESSED) - streams = new KafkaStreams(builder, config) - } catch (MissingMethodException e) { - def producer = Class.forName("org.apache.kafka.streams.kstream.Produced") - .with(Serdes.String(), Serdes.String()) - values.to(STREAM_PROCESSED, producer) - streams = new KafkaStreams(builder.build(), config) - } - streams.start() - - // CONFIGURE PRODUCER - def producerFactory = new DefaultKafkaProducerFactory(senderProps) - def kafkaTemplate = new KafkaTemplate(producerFactory) - - when: - String greeting = "TESTING TESTING 123!" - kafkaTemplate.send(STREAM_PENDING, greeting) - - then: - // check that the message was received - def received = records.poll(10, TimeUnit.SECONDS) - received.value() == greeting.toLowerCase() - received.key() == null - - assertTraces(1) { - trace(0, 5) { - // PRODUCER span 0 - span(0) { - name STREAM_PENDING + " send" - kind PRODUCER - errored false - hasNoParent() - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" STREAM_PENDING - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - // CONSUMER span 0 - span(1) { - name STREAM_PENDING + " process" - kind CONSUMER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" STREAM_PENDING - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - } - } - // STREAMING span 1 - span(2) { - name STREAM_PENDING + " process" - kind CONSUMER - errored false - childOf span(0) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" STREAM_PENDING - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "partition" { it >= 0 } - "offset" 0 - "asdf" "testing" - } - } - // STREAMING span 0 - span(3) { - name STREAM_PROCESSED + " send" - kind PRODUCER - errored false - childOf span(2) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" STREAM_PROCESSED - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - } - } - // CONSUMER span 0 - span(4) { - name STREAM_PROCESSED + " process" - kind CONSUMER - errored false - childOf span(3) - attributes { - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "kafka" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" STREAM_PROCESSED - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "topic" - "${SemanticAttributes.MESSAGING_OPERATION.key}" "process" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - "partition" { it >= 0 } - "offset" 0 - "record.queue_time_ms" { it >= 0 } - "testing" 123 - } - } - } - } - - def headers = received.headers() - headers.iterator().hasNext() - def traceparent = new String(headers.headers("traceparent").iterator().next().value()) - Context context = new HttpTraceContext().extract(Context.root(), "", new TextMapPropagator.Getter() { - @Override - Iterable keys(String carrier) { - return Collections.singleton("traceparent") - } - - @Override - String get(String carrier, String key) { - if (key == "traceparent") { - return traceparent - } - return null - } - }) - def spanContext = Span.fromContext(context).getSpanContext() - spanContext.traceIdAsHexString == TEST_WRITER.traces[0][3].traceId - spanContext.spanIdAsHexString == TEST_WRITER.traces[0][3].spanId - - - cleanup: - producerFactory?.stop() - streams?.close() - consumerContainer?.stop() - } -} diff --git a/instrumentation/khttp-0.1/khttp-0.1.gradle b/instrumentation/khttp-0.1/khttp-0.1.gradle deleted file mode 100644 index de6c835a40..0000000000 --- a/instrumentation/khttp-0.1/khttp-0.1.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = 'khttp' - module = 'khttp' - versions = "(,)" - assertInverse = true - } -} - -dependencies { - library group: 'khttp', name: 'khttp', version: '0.1.0' -} \ No newline at end of file diff --git a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpAdvice.java b/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpAdvice.java deleted file mode 100644 index b0c88feb15..0000000000 --- a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpAdvice.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.khttp; - -import static io.opentelemetry.javaagent.instrumentation.khttp.KHttpHeadersInjectAdapter.asWritable; -import static io.opentelemetry.javaagent.instrumentation.khttp.KHttpTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import java.util.Map; -import khttp.responses.Response; -import net.bytebuddy.asm.Advice; - -public class KHttpAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(value = 0) String method, - @Advice.Argument(value = 1) String uri, - @Advice.Argument(value = 2, readOnly = false) Map headers, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - - callDepth = tracer().getCallDepth(); - if (callDepth.getAndIncrement() == 0) { - span = tracer().startSpan(new RequestWrapper(method, uri, headers)); - if (span.getSpanContext().isValid()) { - headers = asWritable(headers); - scope = tracer().startScope(span, headers); - } - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return Response response, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Local("otelCallDepth") Depth callDepth) { - if (callDepth.decrementAndGet() == 0 && scope != null) { - scope.close(); - if (throwable == null) { - tracer().end(span, response); - } else { - tracer().endExceptionally(span, response, throwable); - } - } - } -} diff --git a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpHeadersInjectAdapter.java b/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpHeadersInjectAdapter.java deleted file mode 100644 index b74c5a0e6e..0000000000 --- a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpHeadersInjectAdapter.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.khttp; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.util.HashMap; -import java.util.Map; - -public class KHttpHeadersInjectAdapter implements TextMapPropagator.Setter> { - - public static Map asWritable(Map headers) { - // Kotlin likes to use read-only data structures, so wrap into new writable map - return new HashMap<>(headers); - } - - public static final KHttpHeadersInjectAdapter SETTER = new KHttpHeadersInjectAdapter(); - - @Override - public void set(Map carrier, String key, String value) { - carrier.put(key, value); - } -} diff --git a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpInstrumentationModule.java b/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpInstrumentationModule.java deleted file mode 100644 index e050d34ad5..0000000000 --- a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpInstrumentationModule.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.khttp; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class KHttpInstrumentationModule extends InstrumentationModule { - - public KHttpInstrumentationModule() { - super("khttp"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new KHttpInstrumentation()); - } - - public static class KHttpInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("khttp.KHttp"); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType(named("khttp.KHttp")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(not(isAbstract())) - .and(named("request")) - .and(takesArgument(0, named("java.lang.String"))) - .and(takesArgument(1, named("java.lang.String"))) - .and(takesArgument(2, named("java.util.Map"))) - .and(returns(named("khttp.responses.Response"))), - KHttpAdvice.class.getName()); - } - } -} diff --git a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpTracer.java b/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpTracer.java deleted file mode 100644 index 124c70cfc2..0000000000 --- a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/KHttpTracer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.khttp; - -import static io.opentelemetry.javaagent.instrumentation.khttp.KHttpHeadersInjectAdapter.SETTER; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap.Depth; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; -import khttp.KHttp; -import khttp.responses.Response; - -public class KHttpTracer extends HttpClientTracer, Response> { - private static final KHttpTracer TRACER = new KHttpTracer(); - - public static KHttpTracer tracer() { - return TRACER; - } - - public Depth getCallDepth() { - return CallDepthThreadLocalMap.getCallDepth(KHttp.class); - } - - @Override - protected String method(RequestWrapper requestWrapper) { - return requestWrapper.method; - } - - @Override - protected URI url(RequestWrapper requestWrapper) throws URISyntaxException { - return new URI(requestWrapper.uri); - } - - @Override - protected Integer status(Response response) { - return response.getStatusCode(); - } - - @Override - protected String requestHeader(RequestWrapper requestWrapper, String name) { - return requestWrapper.headers.get(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.getHeaders().get(name); - } - - @Override - protected Setter> getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.khttp"; - } -} diff --git a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/RequestWrapper.java b/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/RequestWrapper.java deleted file mode 100644 index 462d6b4298..0000000000 --- a/instrumentation/khttp-0.1/src/main/java/io/opentelemetry/javaagent/instrumentation/khttp/RequestWrapper.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.khttp; - -import java.util.Map; - -public class RequestWrapper { - final String method; - final String uri; - final Map headers; - - public RequestWrapper(String method, String uri, Map headers) { - this.method = method; - this.uri = uri; - this.headers = headers; - } -} diff --git a/instrumentation/khttp-0.1/src/test/groovy/KHttpClientTest.groovy b/instrumentation/khttp-0.1/src/test/groovy/KHttpClientTest.groovy deleted file mode 100644 index 4e834317c5..0000000000 --- a/instrumentation/khttp-0.1/src/test/groovy/KHttpClientTest.groovy +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import khttp.KHttp - -class KHttpClientTest extends HttpClientTest { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - headers.put("User-Agent", "khttp") - // khttp applies the same timeout for both connect and read - def timeoutSeconds = CONNECT_TIMEOUT_MS / 1000 - def response = KHttp.request(method, uri.toString(), headers, Collections.emptyMap(), null, null, null, null, timeoutSeconds) - if (callback != null) { - callback.call() - } - return response.statusCode - } - - @Override - boolean testCircularRedirects() { - return false - } - - @Override - String userAgent() { - return "khttp" - } -} diff --git a/instrumentation/kotlinx-coroutines/kotlinx-coroutines.gradle b/instrumentation/kotlinx-coroutines/kotlinx-coroutines.gradle deleted file mode 100644 index 22076db7b4..0000000000 --- a/instrumentation/kotlinx-coroutines/kotlinx-coroutines.gradle +++ /dev/null @@ -1,26 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply from: "$rootDir/gradle/test-with-kotlin.gradle" - -muzzle { - pass { - group = 'org.jetbrains.kotlinx' - module = 'kotlinx-coroutines-core' - versions = "[1.0.0,1.3.8)" - skipVersions += ['1.3.2-js-ir-01', '1.3.2-js-ir-02'] - } - // 1.3.9 (and beyond?) have changed how artifact names are resolved due to multiplatform variants - pass { - group = 'org.jetbrains.kotlinx' - module = 'kotlinx-coroutines-core-jvm' - versions = "[1.3.9,)" - } -} -dependencies { - implementation deps.opentelemetryKotlin - - compileOnly 'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72' - compileOnly 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7' - - testImplementation deps.kotlin - testImplementation deps.coroutines -} \ No newline at end of file diff --git a/instrumentation/kotlinx-coroutines/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/KotlinCoroutinesInstrumentationHelper.java b/instrumentation/kotlinx-coroutines/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/KotlinCoroutinesInstrumentationHelper.java deleted file mode 100644 index 0f5f8e3a08..0000000000 --- a/instrumentation/kotlinx-coroutines/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/KotlinCoroutinesInstrumentationHelper.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines; - -import io.opentelemetry.context.Context; -import io.opentelemetry.extension.kotlin.ContextExtensionsKt; -import kotlin.coroutines.CoroutineContext; - -public final class KotlinCoroutinesInstrumentationHelper { - - public static CoroutineContext addOpenTelemetryContext(CoroutineContext coroutineContext) { - Context current = Context.current(); - Context inCoroutine = ContextExtensionsKt.getOpenTelemetryContext(coroutineContext); - if (current == inCoroutine) { - return coroutineContext; - } - return coroutineContext.plus(ContextExtensionsKt.asContextElement(current)); - } - - private KotlinCoroutinesInstrumentationHelper() {} -} diff --git a/instrumentation/kotlinx-coroutines/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/KotlinCoroutinesInstrumentationModule.java b/instrumentation/kotlinx-coroutines/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/KotlinCoroutinesInstrumentationModule.java deleted file mode 100644 index 00e17e2809..0000000000 --- a/instrumentation/kotlinx-coroutines/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/KotlinCoroutinesInstrumentationModule.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines; - -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import kotlin.coroutines.CoroutineContext; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class KotlinCoroutinesInstrumentationModule extends InstrumentationModule { - - public KotlinCoroutinesInstrumentationModule() { - super("kotlinx-coroutines"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new CoroutineScopeLaunchInstrumentation()); - } - - public static class CoroutineScopeLaunchInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("kotlinx.coroutines.BuildersKt"); - } - - @Override - public Map, String> transformers() { - final Map, String> transformers = new HashMap<>(); - transformers.put( - (named("launch").or(named("launch$default"))) - .and(takesArgument(1, named("kotlin.coroutines.CoroutineContext"))), - KotlinCoroutinesInstrumentationModule.class.getName() + "$LaunchAdvice"); - transformers.put( - (named("runBlocking").or(named("runBlocking$default"))) - .and(takesArgument(0, named("kotlin.coroutines.CoroutineContext"))), - KotlinCoroutinesInstrumentationModule.class.getName() + "$RunBlockingAdvice"); - return transformers; - } - } - - public static class LaunchAdvice { - @Advice.OnMethodEnter - public static void enter( - @Advice.Argument(value = 1, readOnly = false) CoroutineContext coroutineContext) { - coroutineContext = - KotlinCoroutinesInstrumentationHelper.addOpenTelemetryContext(coroutineContext); - } - } - - public static class RunBlockingAdvice { - @Advice.OnMethodEnter - public static void enter( - @Advice.Argument(value = 0, readOnly = false) CoroutineContext coroutineContext) { - coroutineContext = - KotlinCoroutinesInstrumentationHelper.addOpenTelemetryContext(coroutineContext); - } - } -} diff --git a/instrumentation/kotlinx-coroutines/src/test/groovy/KotlinCoroutineInstrumentationTest.groovy b/instrumentation/kotlinx-coroutines/src/test/groovy/KotlinCoroutineInstrumentationTest.groovy deleted file mode 100644 index f023b393af..0000000000 --- a/instrumentation/kotlinx-coroutines/src/test/groovy/KotlinCoroutineInstrumentationTest.groovy +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.common.AttributeKey -import io.opentelemetry.instrumentation.test.AgentTestRunner -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ThreadPoolDispatcherKt - -class KotlinCoroutineInstrumentationTest extends AgentTestRunner { - - static dispatchersToTest = [ - Dispatchers.Default, - Dispatchers.IO, - Dispatchers.Unconfined, - ThreadPoolDispatcherKt.newFixedThreadPoolContext(2, "Fixed-Thread-Pool"), - ThreadPoolDispatcherKt.newSingleThreadContext("Single-Thread"), - ] - - def "kotlin traced across channels"() { - setup: - KotlinCoroutineTests kotlinTest = new KotlinCoroutineTests(dispatcher) - - when: - kotlinTest.tracedAcrossChannels() - - then: - assertTraces(1) { - trace(0, 7) { - span(0) { - name "parent" - attributes { - } - } - (0..2).each { - span("produce_$it") { - childOf span(0) - attributes { - } - } - span("consume_$it") { - childOf span(0) - attributes { - } - } - } - } - } - - where: - dispatcher << dispatchersToTest - } - - def "kotlin cancellation prevents trace"() { - setup: - KotlinCoroutineTests kotlinTest = new KotlinCoroutineTests(dispatcher) - - when: - kotlinTest.tracePreventedByCancellation() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - attributes { - } - } - span("preLaunch") { - childOf span(0) - attributes { - } - } - } - } - - where: - dispatcher << dispatchersToTest - } - - def "kotlin propagates across nested jobs"() { - setup: - KotlinCoroutineTests kotlinTest = new KotlinCoroutineTests(dispatcher) - - when: - kotlinTest.tracedAcrossThreadsWithNested() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - attributes { - } - } - span("nested") { - childOf span(0) - attributes { - } - } - } - } - - where: - dispatcher << dispatchersToTest - } - - def "kotlin either deferred completion"() { - setup: - KotlinCoroutineTests kotlinTest = new KotlinCoroutineTests(Dispatchers.Default) - - when: - kotlinTest.traceWithDeferred() - - then: - assertTraces(1) { - trace(0, 5) { - span(0) { - name "parent" - attributes { - } - } - span("future1") { - childOf span(0) - attributes { - } - } - span("keptPromise") { - childOf span(0) - attributes { - } - } - span("keptPromise2") { - childOf span(0) - attributes { - } - } - span("brokenPromise") { - childOf span(0) - attributes { - } - } - } - } - - where: - dispatcher << dispatchersToTest - } - - def "kotlin first completed deferred"() { - setup: - KotlinCoroutineTests kotlinTest = new KotlinCoroutineTests(Dispatchers.Default) - - when: - kotlinTest.tracedWithDeferredFirstCompletions() - - then: - assertTraces(1) { - trace(0, 4) { - span(0) { - name "parent" - attributes { - } - } - span("timeout1") { - childOf span(0) - attributes { - } - } - span("timeout2") { - childOf span(0) - attributes { - } - } - span("timeout3") { - childOf span(0) - attributes { - } - } - } - } - - where: - dispatcher << dispatchersToTest - } - - def "test concurrent suspend functions"() { - setup: - KotlinCoroutineTests kotlinTest = new KotlinCoroutineTests(Dispatchers.Default) - int numIters = 100 - HashSet seenItersA = new HashSet<>() - HashSet seenItersB = new HashSet<>() - HashSet expectedIters = new HashSet<>((0L..(numIters - 1)).toList()) - - when: - kotlinTest.launchConcurrentSuspendFunctions(numIters) - - then: - // This generates numIters each of "a calls a2" and "b calls b2" traces. Each - // trace should have a single pair of spans (a and a2) and each of those spans - // should have the same iteration number (attribute "iter"). - // The traces are in some random order, so let's keep track and make sure we see - // each iteration # exactly once - assertTraces(numIters * 2) { - for (int i = 0; i < numIters * 2; i++) { - trace(i, 2) { - boolean a = false - long iter = -1 - span(0) { - a = span.name.matches("a") - iter = span.getAttributes().get(AttributeKey.longKey("iter")) - (a ? seenItersA : seenItersB).add(iter) - name(a ? "a" : "b") - } - span(1) { - name(a ? "a2" : "b2") - childOf(span(0)) - assert span.getAttributes().get(AttributeKey.longKey("iter")) == iter - - } - } - } - } - assert seenItersA.equals(expectedIters) - assert seenItersB.equals(expectedIters) - } -} diff --git a/instrumentation/kotlinx-coroutines/src/test/kotlin/KotlinCoroutineTests.kt b/instrumentation/kotlinx-coroutines/src/test/kotlin/KotlinCoroutineTests.kt deleted file mode 100644 index 290e6e4785..0000000000 --- a/instrumentation/kotlinx-coroutines/src/test/kotlin/KotlinCoroutineTests.kt +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.trace.Tracer -import io.opentelemetry.extension.kotlin.asContextElement -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge -import java.util.concurrent.TimeUnit -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.channels.actor -import kotlinx.coroutines.channels.consumeEach -import kotlinx.coroutines.channels.produce -import kotlinx.coroutines.channels.toChannel -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.selects.select -import kotlinx.coroutines.withContext -import kotlinx.coroutines.withTimeout -import kotlinx.coroutines.yield - -class KotlinCoroutineTests(private val dispatcher: CoroutineDispatcher) { - // Java8BytecodeBridge is needed in order to support Kotlin which generally targets Java 6 bytecode - val tracer: Tracer = Java8BytecodeBridge.getGlobalTracer("io.opentelemetry.auto") - - fun tracedAcrossChannels() = runTest { - - val producer = produce { - repeat(3) { - tracedChild("produce_$it") - send(it) - } - } - - val actor = actor { - consumeEach { - tracedChild("consume_$it") - } - } - - producer.toChannel(actor) - actor.close() - } - - fun tracePreventedByCancellation() { - - kotlin.runCatching { - runTest { - tracedChild("preLaunch") - - launch(start = CoroutineStart.UNDISPATCHED) { - throw Exception("Child Error") - } - - yield() - - tracedChild("postLaunch") - } - } - } - - fun tracedAcrossThreadsWithNested() = runTest { - val goodDeferred = async { 1 } - - launch { - goodDeferred.await() - launch { tracedChild("nested") } - } - } - - fun traceWithDeferred() = runTest { - - val keptPromise = CompletableDeferred() - val brokenPromise = CompletableDeferred() - val afterPromise = async { - keptPromise.await() - tracedChild("keptPromise") - } - val afterPromise2 = async { - keptPromise.await() - tracedChild("keptPromise2") - } - val failedAfterPromise = async { - brokenPromise - .runCatching { await() } - .onFailure { tracedChild("brokenPromise") } - } - - launch { - tracedChild("future1") - keptPromise.complete(true) - brokenPromise.completeExceptionally(IllegalStateException()) - } - - listOf(afterPromise, afterPromise2, failedAfterPromise).awaitAll() - } - - /** - * @return Number of expected spans in the trace - */ - fun tracedWithDeferredFirstCompletions() = runTest { - - val children = listOf( - async { - tracedChild("timeout1") - false - }, - async { - tracedChild("timeout2") - false - }, - async { - tracedChild("timeout3") - true - } - ) - - withTimeout(TimeUnit.SECONDS.toMillis(30)) { - select { - children.forEach { child -> - child.onAwait { it } - } - } - } - } - - fun launchConcurrentSuspendFunctions(numIters: Int) { - runBlocking { - for (i in 0 until numIters) { - GlobalScope.launch { - a(i.toLong()) - } - GlobalScope.launch { - b(i.toLong()) - } - } - } - } - - suspend fun a(iter: Long) { - var span = tracer.spanBuilder("a").startSpan() - span.setAttribute("iter", iter) - withContext(span.asContextElement()) { - delay(10) - a2(iter) - } - span.end() - } - suspend fun a2(iter: Long) { - var span = tracer.spanBuilder("a2").startSpan() - span.setAttribute("iter", iter) - withContext(span.asContextElement()) { - delay(10) - } - span.end() - } - suspend fun b(iter: Long) { - var span = tracer.spanBuilder("b").startSpan() - span.setAttribute("iter", iter) - withContext(span.asContextElement()) { - delay(10) - b2(iter) - } - span.end() - } - suspend fun b2(iter: Long) { - var span = tracer.spanBuilder("b2").startSpan() - span.setAttribute("iter", iter) - withContext(span.asContextElement()) { - delay(10) - } - span.end() - } - - fun tracedChild(opName: String) { - tracer.spanBuilder(opName).startSpan().end() - } - - private fun runTest(block: suspend CoroutineScope.() -> T): T { - val parentSpan = tracer.spanBuilder("parent").startSpan() - val parentScope = parentSpan.makeCurrent() - try { - return runBlocking(dispatcher, block = block) - } finally { - parentSpan.end() - parentScope.close() - } - } -} diff --git a/instrumentation/kubernetes-client-7.0/kubernetes-client-7.0.gradle b/instrumentation/kubernetes-client-7.0/kubernetes-client-7.0.gradle deleted file mode 100644 index a363901bdb..0000000000 --- a/instrumentation/kubernetes-client-7.0/kubernetes-client-7.0.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.kubernetes" - module = "client-java-api" - versions = "[7.0.0,)" - assertInverse = true - } -} - -dependencies { - library(group: 'io.kubernetes', name: 'client-java-api', version: '7.0.0') -} - diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java deleted file mode 100644 index 4438e36c55..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientInstrumentationModule.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.kubernetes.client.openapi.ApiClient; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; -import okhttp3.Interceptor; - -@AutoService(InstrumentationModule.class) -public class KubernetesClientInstrumentationModule extends InstrumentationModule { - - public KubernetesClientInstrumentationModule() { - super("kubernetes-client", "kubernetes-client-3.0"); - } - - @Override - protected String[] additionalHelperClassNames() { - return new String[] { - "com.google.common.base.Strings", - }; - } - - @Override - public List typeInstrumentations() { - return singletonList(new ApiClientInstrumentation()); - } - - public static class ApiClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("io.kubernetes.client.openapi.ApiClient"); - } - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("io.kubernetes.client.openapi.ApiClient")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - ElementMatchers.isMethod() - .and(named("initHttpClient")) - .and(ElementMatchers.takesArguments(1)) - .and(ElementMatchers.takesArgument(0, named("java.util.List"))), - KubernetesClientInstrumentationModule.class.getName() + "$KubernetesAdvice"); - } - } - - public static class KubernetesAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void addTracingInterceptor( - @Advice.This ApiClient apiClient, @Advice.Argument(0) List interceptors) { - - for (Interceptor interceptor : interceptors) { - if (interceptor instanceof TracingInterceptor) { - return; - } - } - - apiClient.setHttpClient( - apiClient.getHttpClient().newBuilder().addInterceptor(new TracingInterceptor()).build()); - } - } -} diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTracer.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTracer.java deleted file mode 100644 index f897242eb0..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTracer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import okhttp3.Request; -import okhttp3.Response; - -public class KubernetesClientTracer extends HttpClientTracer { - private static final KubernetesClientTracer TRACER = new KubernetesClientTracer(); - - public static KubernetesClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(Request httpRequest) { - return httpRequest.method(); - } - - @Override - protected URI url(Request httpRequest) { - return httpRequest.url().uri(); - } - - @Override - protected Integer status(Response httpResponse) { - return httpResponse.code(); - } - - @Override - protected String requestHeader(Request request, String name) { - return request.header(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.header(name); - } - - @Override - protected Setter getSetter() { - // TODO (trask) no propagation implemented yet? - return null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.kubernetes-client"; - } - - /** This method is overridden to allow other classes in this package to call it. */ - @Override - protected Span onRequest(Span span, Request request) { - return super.onRequest(span, request); - } - - /** - * This method is used to generate an acceptable CLIENT span (operation) name based on a given - * KubernetesRequestDigest. - */ - public Span startSpan(KubernetesRequestDigest digest) { - return tracer - .spanBuilder(digest.toString()) - .setSpanKind(CLIENT) - .setAttribute("namespace", digest.getResourceMeta().getNamespace()) - .setAttribute("name", digest.getResourceMeta().getName()) - .startSpan(); - } -} diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java deleted file mode 100644 index aa2b1c4fe6..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -import com.google.common.base.Strings; -import java.util.regex.Pattern; -import okhttp3.Request; - -class KubernetesRequestDigest { - - public static final Pattern RESOURCE_URL_PATH_PATTERN = - Pattern.compile("^/(api|apis)(/\\S+)?/v\\d\\w*/\\S+"); - - KubernetesRequestDigest( - String urlPath, - boolean isNonResourceRequest, - KubernetesResource resourceMeta, - KubernetesVerb verb) { - this.urlPath = urlPath; - this.isNonResourceRequest = isNonResourceRequest; - this.resourceMeta = resourceMeta; - this.verb = verb; - } - - public static KubernetesRequestDigest parse(Request request) { - String urlPath = request.url().encodedPath(); - if (!isResourceRequest(urlPath)) { - return nonResource(urlPath); - } - try { - KubernetesResource resourceMeta; - if (urlPath.startsWith("/api/v1")) { - resourceMeta = KubernetesResource.parseCoreResource(urlPath); - } else { - resourceMeta = KubernetesResource.parseRegularResource(urlPath); - } - - return new KubernetesRequestDigest( - urlPath, - false, - resourceMeta, - KubernetesVerb.of( - request.method(), hasNamePathParameter(resourceMeta), hasWatchParameter(request))); - } catch (ParseKubernetesResourceException e) { - return nonResource(urlPath); - } - } - - private static KubernetesRequestDigest nonResource(String urlPath) { - KubernetesRequestDigest digest = new KubernetesRequestDigest(urlPath, true, null, null); - return digest; - } - - public static boolean isResourceRequest(String urlPath) { - return RESOURCE_URL_PATH_PATTERN.matcher(urlPath).matches(); - } - - private static boolean hasWatchParameter(Request request) { - return !Strings.isNullOrEmpty(request.url().queryParameter("watch")); - } - - private static boolean hasNamePathParameter(KubernetesResource resource) { - return !Strings.isNullOrEmpty(resource.getName()); - } - - private final String urlPath; - private final boolean isNonResourceRequest; - - private final KubernetesResource resourceMeta; - private final KubernetesVerb verb; - - public String getUrlPath() { - return urlPath; - } - - public boolean isNonResourceRequest() { - return isNonResourceRequest; - } - - public KubernetesResource getResourceMeta() { - return resourceMeta; - } - - public KubernetesVerb getVerb() { - return verb; - } - - @Override - public String toString() { - if (isNonResourceRequest) { - return new StringBuilder().append(verb).append(' ').append(urlPath).toString(); - } - - String groupVersion; - if (Strings.isNullOrEmpty(resourceMeta.getApiGroup())) { // core resource - groupVersion = ""; - } else { // regular resource - groupVersion = resourceMeta.getApiGroup() + "/" + resourceMeta.getApiVersion(); - } - - String targetResourceName; - if (Strings.isNullOrEmpty(resourceMeta.getSubResource())) { - targetResourceName = resourceMeta.getResource(); - } else { // subresource - targetResourceName = resourceMeta.getResource() + "/" + resourceMeta.getSubResource(); - } - - return new StringBuilder() - .append(verb.value()) - .append(' ') - .append(groupVersion) - .append(' ') - .append(targetResourceName) - .toString(); - } -} diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java deleted file mode 100644 index a3aebc983b..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class KubernetesResource { - - public static final Pattern CORE_RESOURCE_URL_PATH_PATTERN = - Pattern.compile( - "^/api/v1(/namespaces/(?[\\w-]+))?/(?[\\w-]+)(/(?[\\w-]+))?(/(?[\\w-]+))?"); - - public static final Pattern REGULAR_RESOURCE_URL_PATH_PATTERN = - Pattern.compile( - "^/apis/(?\\S+?)/(?\\S+?)(/namespaces/(?[\\w-]+))?/(?[\\w-]+)(/(?[\\w-]+))?(/(?[\\w-]+))?"); - - public static KubernetesResource parseCoreResource(String urlPath) - throws ParseKubernetesResourceException { - Matcher matcher = CORE_RESOURCE_URL_PATH_PATTERN.matcher(urlPath); - if (!matcher.matches()) { - throw new ParseKubernetesResourceException(); - } - KubernetesResource resource = - new KubernetesResource( - "", - "v1", - matcher.group("resource"), - matcher.group("subresource"), - matcher.group("namespace"), - matcher.group("name")); - return resource; - } - - public static KubernetesResource parseRegularResource(String urlPath) - throws ParseKubernetesResourceException { - Matcher matcher = REGULAR_RESOURCE_URL_PATH_PATTERN.matcher(urlPath); - if (!matcher.matches()) { - throw new ParseKubernetesResourceException(); - } - KubernetesResource resource = - new KubernetesResource( - matcher.group("group"), - matcher.group("version"), - matcher.group("resource"), - matcher.group("subresource"), - matcher.group("namespace"), - matcher.group("name")); - return resource; - } - - KubernetesResource( - String apiGroup, - String apiVersion, - String resource, - String subResource, - String namespace, - String name) { - this.apiGroup = apiGroup; - this.apiVersion = apiVersion; - this.resource = resource; - this.subResource = subResource; - this.namespace = namespace; - this.name = name; - } - - private final String apiGroup; - private final String apiVersion; - private final String resource; - private final String subResource; - - private final String namespace; - private final String name; - - public String getApiGroup() { - return apiGroup; - } - - public String getApiVersion() { - return apiVersion; - } - - public String getResource() { - return resource; - } - - public String getSubResource() { - return subResource; - } - - public String getNamespace() { - return namespace; - } - - public String getName() { - return name; - } -} diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesVerb.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesVerb.java deleted file mode 100644 index 8d65b8282e..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesVerb.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -public enum KubernetesVerb { - GET("get"), - LIST("list"), - CREATE("create"), - UPDATE("update"), - DELETE("delete"), - PATCH("patch"), - WATCH("watch"), - DELETE_COLLECTION("deleteCollection"); - - private final String value; - - KubernetesVerb(String value) { - this.value = value; - } - - public static KubernetesVerb of( - String httpVerb, boolean hasNamePathParam, boolean hasWatchParam) { - if (hasWatchParam) { - return WATCH; - } - switch (httpVerb) { - case "GET": - if (!hasNamePathParam) { - return LIST; - } - return GET; - case "POST": - return CREATE; - case "PUT": - return UPDATE; - case "PATCH": - return PATCH; - case "DELETE": - if (!hasNamePathParam) { - return DELETE_COLLECTION; - } - return DELETE; - default: - throw new IllegalArgumentException("invalid HTTP verb for kubernetes client"); - } - } - - public String value() { - return value; - } -} diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ParseKubernetesResourceException.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ParseKubernetesResourceException.java deleted file mode 100644 index 2a1b82cdec..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ParseKubernetesResourceException.java +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -class ParseKubernetesResourceException extends Exception {} diff --git a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/TracingInterceptor.java b/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/TracingInterceptor.java deleted file mode 100644 index 63df8b55bc..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/TracingInterceptor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.kubernetesclient; - -import static io.opentelemetry.javaagent.instrumentation.kubernetesclient.KubernetesClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import java.io.IOException; -import okhttp3.Interceptor; -import okhttp3.Response; - -public class TracingInterceptor implements Interceptor { - - @Override - public Response intercept(Chain chain) throws IOException { - - KubernetesRequestDigest digest = KubernetesRequestDigest.parse(chain.request()); - - Span span = tracer().startSpan(digest); - tracer().onRequest(span, chain.request()); - - Context context = Context.current().with(span); - - Response response; - try (Scope scope = context.makeCurrent()) { - response = chain.proceed(chain.request()); - } catch (Exception e) { - tracer().endExceptionally(span, e); - throw e; - } - - tracer().end(span, response); - return response; - } -} diff --git a/instrumentation/kubernetes-client-7.0/src/test/groovy/KubernetesRequestUtilsTest.groovy b/instrumentation/kubernetes-client-7.0/src/test/groovy/KubernetesRequestUtilsTest.groovy deleted file mode 100644 index 19b7f6b5b0..0000000000 --- a/instrumentation/kubernetes-client-7.0/src/test/groovy/KubernetesRequestUtilsTest.groovy +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.javaagent.instrumentation.kubernetesclient.KubernetesRequestDigest -import io.opentelemetry.javaagent.instrumentation.kubernetesclient.KubernetesResource -import io.opentelemetry.javaagent.instrumentation.kubernetesclient.KubernetesVerb -import spock.lang.Specification - -class KubernetesRequestUtilsTest extends Specification { - def "asserting non-resource requests should work"() { - expect: - !KubernetesRequestDigest.isResourceRequest("/api") - !KubernetesRequestDigest.isResourceRequest("/apis") - !KubernetesRequestDigest.isResourceRequest("/apis/v1") - !KubernetesRequestDigest.isResourceRequest("/healthz") - !KubernetesRequestDigest.isResourceRequest("/swagger.json") - !KubernetesRequestDigest.isResourceRequest("/api/v1") - !KubernetesRequestDigest.isResourceRequest("/api/v1/") - !KubernetesRequestDigest.isResourceRequest("/apis/apps/v1") - !KubernetesRequestDigest.isResourceRequest("/apis/apps/v1/") - } - - def "asserting resource requests should work"() { - expect: - KubernetesRequestDigest.isResourceRequest("/apis/example.io/v1/foos") - KubernetesRequestDigest.isResourceRequest("/apis/example.io/v1/namespaces/default/foos") - KubernetesRequestDigest.isResourceRequest("/api/v1/namespaces") - KubernetesRequestDigest.isResourceRequest("/api/v1/pods") - KubernetesRequestDigest.isResourceRequest("/api/v1/namespaces/default/pods") - } - - def "parsing core resource from url-path should work"(String urlPath, String apiGroup, String apiVersion, String resource, String subResource, String namespace, String name) { - expect: - KubernetesResource.parseCoreResource(urlPath).apiGroup == apiGroup - KubernetesResource.parseCoreResource(urlPath).apiVersion == apiVersion - KubernetesResource.parseCoreResource(urlPath).resource == resource - KubernetesResource.parseCoreResource(urlPath).subResource == subResource - KubernetesResource.parseCoreResource(urlPath).namespace == namespace - KubernetesResource.parseCoreResource(urlPath).name == name - - where: - urlPath | apiGroup | apiVersion | resource | subResource | namespace | name - "/api/v1/pods" | "" | "v1" | "pods" | null | null | null - "/api/v1/namespaces/default/pods" | "" | "v1" | "pods" | null | "default" | null - "/api/v1/namespaces/default/pods/foo" | "" | "v1" | "pods" | null | "default" | "foo" - "/api/v1/namespaces/default/pods/foo/exec" | "" | "v1" | "pods" | "exec" | "default" | "foo" - } - - def "parsing regular non-core resource from url-path should work"(String urlPath, String apiGroup, String apiVersion, String resource, String subResource, String namespace, String name) { - expect: - KubernetesResource.parseRegularResource(urlPath).apiGroup == apiGroup - KubernetesResource.parseRegularResource(urlPath).apiVersion == apiVersion - KubernetesResource.parseRegularResource(urlPath).resource == resource - KubernetesResource.parseRegularResource(urlPath).subResource == subResource - KubernetesResource.parseRegularResource(urlPath).namespace == namespace - KubernetesResource.parseRegularResource(urlPath).name == name - - where: - urlPath | apiGroup | apiVersion | resource | subResource | namespace | name - "/apis/apps/v1/deployments" | "apps" | "v1" | "deployments" | null | null | null - "/apis/apps/v1/namespaces/default/deployments" | "apps" | "v1" | "deployments" | null | "default" | null - "/apis/apps/v1/namespaces/default/deployments/foo" | "apps" | "v1" | "deployments" | null | "default" | "foo" - "/apis/apps/v1/namespaces/default/deployments/foo/status" | "apps" | "v1" | "deployments" | "status" | "default" | "foo" - "/apis/example.io/v1alpha1/foos" | "example.io" | "v1alpha1" | "foos" | null | null | null - "/apis/example.io/v1alpha1/namespaces/default/foos" | "example.io" | "v1alpha1" | "foos" | null | "default" | null - "/apis/example.io/v1alpha1/namespaces/default/foos/foo" | "example.io" | "v1alpha1" | "foos" | null | "default" | "foo" - "/apis/example.io/v1alpha1/namespaces/default/foos/foo/status" | "example.io" | "v1alpha1" | "foos" | "status" | "default" | "foo" - } - - def "parsing kubernetes request verbs should work"(String httpVerb, boolean hasNamePathParam, boolean hasWatchParam, KubernetesVerb kubernetesVerb) { - expect: - KubernetesVerb.of(httpVerb, hasNamePathParam, hasWatchParam) == kubernetesVerb - - where: - httpVerb | hasNamePathParam | hasWatchParam | kubernetesVerb - "GET" | true | false | KubernetesVerb.GET - "GET" | false | true | KubernetesVerb.WATCH - "GET" | false | false | KubernetesVerb.LIST - "POST" | false | false | KubernetesVerb.CREATE - "PUT" | false | false | KubernetesVerb.UPDATE - "PATCH" | false | false | KubernetesVerb.PATCH - "DELETE" | true | false | KubernetesVerb.DELETE - "DELETE" | false | false | KubernetesVerb.DELETE_COLLECTION - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy b/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy index 6c38e91134..f71b49e34b 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy @@ -15,9 +15,9 @@ import com.lambdaworks.redis.api.async.RedisAsyncCommands import com.lambdaworks.redis.api.sync.RedisCommands import com.lambdaworks.redis.codec.Utf8StringCodec import com.lambdaworks.redis.protocol.AsyncCommand +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.concurrent.CancellationException import java.util.concurrent.TimeUnit import java.util.function.BiConsumer diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy b/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy index 78248cddeb..651c882be5 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy @@ -10,9 +10,9 @@ import com.lambdaworks.redis.RedisClient import com.lambdaworks.redis.RedisConnectionException import com.lambdaworks.redis.api.StatefulConnection import com.lambdaworks.redis.api.sync.RedisCommands +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import redis.embedded.RedisServer import spock.lang.Shared diff --git a/instrumentation/lettuce/lettuce-4.0/lettuce-4.0.gradle b/instrumentation/lettuce/lettuce-4.0/lettuce-4.0.gradle deleted file mode 100644 index 62563780d2..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/lettuce-4.0.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "biz.paluch.redis" - module = "lettuce" - versions = "[4.0.Final,)" - assertInverse = true - } -} - - -dependencies { - library group: 'biz.paluch.redis', name: 'lettuce', version: '4.0.Final' - - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' - - latestDepTestLibrary group: 'biz.paluch.redis', name: 'lettuce', version: '4.+' -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java deleted file mode 100644 index b81cbef1cc..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import static com.lambdaworks.redis.protocol.CommandKeyword.SEGFAULT; -import static com.lambdaworks.redis.protocol.CommandType.DEBUG; -import static com.lambdaworks.redis.protocol.CommandType.SHUTDOWN; - -import com.lambdaworks.redis.RedisURI; -import com.lambdaworks.redis.protocol.AsyncCommand; -import com.lambdaworks.redis.protocol.CommandType; -import com.lambdaworks.redis.protocol.ProtocolKeyword; -import com.lambdaworks.redis.protocol.RedisCommand; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import java.util.EnumSet; -import java.util.Set; -import java.util.concurrent.CancellationException; - -public final class InstrumentationPoints { - - private static final Set NON_INSTRUMENTING_COMMANDS = EnumSet.of(SHUTDOWN, DEBUG); - - public static SpanWithScope beforeCommand(RedisCommand command) { - Span span = LettuceDatabaseClientTracer.tracer().startSpan(null, command); - return new SpanWithScope(span, LettuceDatabaseClientTracer.tracer().startScope(span)); - } - - public static void afterCommand( - RedisCommand command, - SpanWithScope spanWithScope, - Throwable throwable, - AsyncCommand asyncCommand) { - Span span = spanWithScope.getSpan(); - if (throwable != null) { - LettuceDatabaseClientTracer.tracer().endExceptionally(span, throwable); - } else if (expectsResponse(command)) { - asyncCommand.handleAsync( - (value, ex) -> { - if (ex == null) { - LettuceDatabaseClientTracer.tracer().end(span); - } else if (ex instanceof CancellationException) { - span.setAttribute("db.command.cancelled", true); - LettuceDatabaseClientTracer.tracer().end(span); - } else { - LettuceDatabaseClientTracer.tracer().endExceptionally(span, ex); - } - return null; - }); - } else { - // No response is expected, so we must finish the span now. - LettuceDatabaseClientTracer.tracer().end(span); - } - spanWithScope.closeScope(); - } - - public static SpanWithScope beforeConnect(RedisURI redisUri) { - Span span = LettuceConnectionDatabaseClientTracer.tracer().startSpan(redisUri, "CONNECT"); - return new SpanWithScope(span, LettuceConnectionDatabaseClientTracer.tracer().startScope(span)); - } - - public static void afterConnect(SpanWithScope spanWithScope, Throwable throwable) { - Span span = spanWithScope.getSpan(); - if (throwable != null) { - LettuceConnectionDatabaseClientTracer.tracer().endExceptionally(span, throwable); - } else { - LettuceConnectionDatabaseClientTracer.tracer().end(span); - } - spanWithScope.closeScope(); - } - - /** - * Determines whether a redis command should finish its relevant span early (as soon as tags are - * added and the command is executed) because these commands have no return values/call backs, so - * we must close the span early in order to provide info for the users. - * - * @return false if the span should finish early (the command will not have a return value) - */ - public static boolean expectsResponse(RedisCommand command) { - ProtocolKeyword keyword = command.getType(); - return !(isNonInstrumentingCommand(keyword) || isNonInstrumentingKeyword(keyword)); - } - - private static boolean isNonInstrumentingCommand(ProtocolKeyword keyword) { - return keyword instanceof CommandType && NON_INSTRUMENTING_COMMANDS.contains(keyword); - } - - private static boolean isNonInstrumentingKeyword(ProtocolKeyword keyword) { - return keyword == SEGFAULT; - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAbstractDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAbstractDatabaseClientTracer.java deleted file mode 100644 index ae15f77e39..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAbstractDatabaseClientTracer.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import com.lambdaworks.redis.RedisURI; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.net.InetSocketAddress; - -public abstract class LettuceAbstractDatabaseClientTracer - extends DatabaseClientTracer { - - @Override - protected String dbSystem(RedisURI connection) { - return DbSystem.REDIS; - } - - @Override - protected InetSocketAddress peerAddress(RedisURI redisUri) { - return new InetSocketAddress(redisUri.getHost(), redisUri.getPort()); - } - - @Override - public Span onConnection(Span span, RedisURI connection) { - if (connection != null && connection.getDatabase() != 0) { - span.setAttribute(SemanticAttributes.DB_REDIS_DATABASE_INDEX, connection.getDatabase()); - } - return super.onConnection(span, connection); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.lettuce"; - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsAdvice.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsAdvice.java deleted file mode 100644 index a40aea3798..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsAdvice.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import com.lambdaworks.redis.protocol.AsyncCommand; -import com.lambdaworks.redis.protocol.RedisCommand; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import net.bytebuddy.asm.Advice; - -public class LettuceAsyncCommandsAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope onEnter(@Advice.Argument(0) RedisCommand command) { - return InstrumentationPoints.beforeCommand(command); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Argument(0) RedisCommand command, - @Advice.Enter SpanWithScope spanWithScope, - @Advice.Thrown Throwable throwable, - @Advice.Return AsyncCommand asyncCommand) { - InstrumentationPoints.afterCommand(command, spanWithScope, throwable, asyncCommand); - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsInstrumentation.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsInstrumentation.java deleted file mode 100644 index 030964d113..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncCommandsInstrumentation.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class LettuceAsyncCommandsInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.lambdaworks.redis.AbstractRedisAsyncCommands"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("dispatch")) - .and(takesArgument(0, named("com.lambdaworks.redis.protocol.RedisCommand"))), - LettuceAsyncCommandsAdvice.class.getName()); - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceClientInstrumentation.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceClientInstrumentation.java deleted file mode 100644 index 8fcbeb51eb..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceClientInstrumentation.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class LettuceClientInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("com.lambdaworks.redis.RedisClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("connectStandalone")), RedisConnectionAdvice.class.getName()); - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java deleted file mode 100644 index 8dd484cb5b..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceConnectionDatabaseClientTracer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -public class LettuceConnectionDatabaseClientTracer - extends LettuceAbstractDatabaseClientTracer { - - private static final LettuceConnectionDatabaseClientTracer TRACER = - new LettuceConnectionDatabaseClientTracer(); - - public static LettuceConnectionDatabaseClientTracer tracer() { - return TRACER; - } - - @Override - protected String normalizeQuery(String command) { - return command; - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java deleted file mode 100644 index efee20a04c..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDatabaseClientTracer.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import com.lambdaworks.redis.protocol.RedisCommand; - -public class LettuceDatabaseClientTracer - extends LettuceAbstractDatabaseClientTracer> { - - private static final LettuceDatabaseClientTracer TRACER = new LettuceDatabaseClientTracer(); - - public static LettuceDatabaseClientTracer tracer() { - return TRACER; - } - - @Override - protected String normalizeQuery(RedisCommand command) { - return command.getType().name(); - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceInstrumentationModule.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceInstrumentationModule.java deleted file mode 100644 index b01620667c..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceInstrumentationModule.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class LettuceInstrumentationModule extends InstrumentationModule { - public LettuceInstrumentationModule() { - super("lettuce", "lettuce-4.0"); - } - - @Override - public List typeInstrumentations() { - return asList(new LettuceClientInstrumentation(), new LettuceAsyncCommandsInstrumentation()); - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/RedisConnectionAdvice.java b/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/RedisConnectionAdvice.java deleted file mode 100644 index 3abc55e7c1..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/RedisConnectionAdvice.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; - -import com.lambdaworks.redis.RedisURI; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import net.bytebuddy.asm.Advice; - -public class RedisConnectionAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope onEnter(@Advice.Argument(1) RedisURI redisUri) { - return InstrumentationPoints.beforeConnect(redisUri); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit(@Advice.Enter SpanWithScope scope, @Advice.Thrown Throwable throwable) { - InstrumentationPoints.afterConnect(scope, throwable); - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/test/groovy/LettuceAsyncClientTest.groovy b/instrumentation/lettuce/lettuce-4.0/src/test/groovy/LettuceAsyncClientTest.groovy deleted file mode 100644 index f71b49e34b..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/test/groovy/LettuceAsyncClientTest.groovy +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import com.lambdaworks.redis.ClientOptions -import com.lambdaworks.redis.RedisClient -import com.lambdaworks.redis.RedisConnectionException -import com.lambdaworks.redis.RedisFuture -import com.lambdaworks.redis.RedisURI -import com.lambdaworks.redis.api.StatefulConnection -import com.lambdaworks.redis.api.async.RedisAsyncCommands -import com.lambdaworks.redis.api.sync.RedisCommands -import com.lambdaworks.redis.codec.Utf8StringCodec -import com.lambdaworks.redis.protocol.AsyncCommand -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.concurrent.CancellationException -import java.util.concurrent.TimeUnit -import java.util.function.BiConsumer -import java.util.function.BiFunction -import java.util.function.Consumer -import java.util.function.Function -import redis.embedded.RedisServer -import spock.lang.Shared -import spock.util.concurrent.AsyncConditions - -class LettuceAsyncClientTest extends AgentTestRunner { - public static final String HOST = "localhost" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = new ClientOptions.Builder().autoReconnect(false).build() - - @Shared - int port - @Shared - int incorrectPort - @Shared - String dbAddr - @Shared - String dbAddrNonExistent - @Shared - String dbUriNonExistent - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - @Shared - Map testHashMap = [ - firstname: "John", - lastname : "Doe", - age : "53" - ] - - RedisClient redisClient - StatefulConnection connection - RedisAsyncCommands asyncCommands - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - incorrectPort = PortUtils.randomOpenPort() - dbAddr = HOST + ":" + port + "/" + DB_INDEX - dbAddrNonExistent = HOST + ":" + incorrectPort + "/" + DB_INDEX - dbUriNonExistent = "redis://" + dbAddrNonExistent - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - println "Using redis: $redisServer.args" - redisServer.start() - redisClient.setOptions(CLIENT_OPTIONS) - - connection = redisClient.connect() - asyncCommands = connection.async() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - - // 1 set + 1 connect trace - TEST_WRITER.waitForTraces(2) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisServer.stop() - } - - def "connect using get on ConnectionFuture"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - StatefulConnection connection = testConnectionClient.connect(new Utf8StringCodec(), - new RedisURI(HOST, port, 3, TimeUnit.SECONDS)) - - then: - connection != null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" HOST - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" port - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "CONNECT" - } - } - } - } - - cleanup: - connection.close() - } - - def "connect exception inside the connection future"() { - setup: - RedisClient testConnectionClient = RedisClient.create(dbUriNonExistent) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - StatefulConnection connection = testConnectionClient.connect(new Utf8StringCodec(), - new RedisURI(HOST, incorrectPort, 3, TimeUnit.SECONDS)) - - then: - connection == null - thrown RedisConnectionException - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored true - errorEvent RedisConnectionException, String - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" HOST - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" incorrectPort - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "CONNECT" - } - } - } - } - } - - def "set command using Future get with timeout"() { - setup: - RedisFuture redisFuture = asyncCommands.set("TESTSETKEY", "TESTSETVAL") - String res = redisFuture.get(3, TimeUnit.SECONDS) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "SET" - } - } - } - } - } - - def "get command chained with thenAccept"() { - setup: - def conds = new AsyncConditions() - Consumer consumer = new Consumer() { - @Override - void accept(String res) { - conds.evaluate { - assert res == "TESTVAL" - } - } - } - - when: - RedisFuture redisFuture = asyncCommands.get("TESTKEY") - redisFuture.thenAccept(consumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "GET" - } - } - } - } - } - - // to make sure instrumentation's chained completion stages won't interfere with user's, while still - // recording metrics - def "get non existent key command with handleAsync and chained with thenApply"() { - setup: - def conds = new AsyncConditions() - String successStr = "KEY MISSING" - BiFunction firstStage = new BiFunction() { - @Override - String apply(String res, Throwable throwable) { - conds.evaluate { - assert res == null - assert throwable == null - } - return (res == null ? successStr : res) - } - } - Function secondStage = new Function() { - @Override - Object apply(String input) { - conds.evaluate { - assert input == successStr - } - return null - } - } - - when: - RedisFuture redisFuture = asyncCommands.get("NON_EXISTENT_KEY") - redisFuture.handleAsync(firstStage).thenApply(secondStage) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "GET" - } - } - } - } - } - - def "command with no arguments using a biconsumer"() { - setup: - def conds = new AsyncConditions() - BiConsumer biConsumer = new BiConsumer() { - @Override - void accept(String keyRetrieved, Throwable throwable) { - conds.evaluate { - assert keyRetrieved != null - } - } - } - - when: - RedisFuture redisFuture = asyncCommands.randomkey() - redisFuture.whenCompleteAsync(biConsumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "RANDOMKEY" - } - } - } - } - } - - def "hash set and then nest apply to hash getall"() { - setup: - def conds = new AsyncConditions() - - when: - RedisFuture hmsetFuture = asyncCommands.hmset("TESTHM", testHashMap) - hmsetFuture.thenApplyAsync(new Function() { - @Override - Object apply(String setResult) { - TEST_WRITER.waitForTraces(1) // Wait for 'hmset' trace to get written - conds.evaluate { - assert setResult == "OK" - } - RedisFuture> hmGetAllFuture = asyncCommands.hgetall("TESTHM") - hmGetAllFuture.exceptionally(new Function>() { - @Override - Map apply(Throwable throwable) { - println("unexpected:" + throwable.toString()) - throwable.printStackTrace() - assert false - return null - } - }) - hmGetAllFuture.thenAccept(new Consumer>() { - @Override - void accept(Map hmGetAllResult) { - conds.evaluate { - assert testHashMap == hmGetAllResult - } - } - }) - return null - } - }) - - then: - conds.await() - assertTraces(2) { - trace(0, 1) { - span(0) { - name "HMSET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "HMSET" - } - } - } - trace(1, 1) { - span(0) { - name "HGETALL" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "HGETALL" - } - } - } - } - } - - def "command completes exceptionally"() { - setup: - // turn off auto flush to complete the command exceptionally manually - asyncCommands.setAutoFlushCommands(false) - def conds = new AsyncConditions() - RedisFuture redisFuture = asyncCommands.del("key1", "key2") - boolean completedExceptionally = ((AsyncCommand) redisFuture).completeExceptionally(new IllegalStateException("TestException")) - redisFuture.exceptionally({ - throwable -> - conds.evaluate { - assert throwable != null - assert throwable instanceof IllegalStateException - assert throwable.getMessage() == "TestException" - } - throw throwable - }) - - when: - // now flush and execute the command - asyncCommands.flushCommands() - redisFuture.get() - - then: - conds.await() - completedExceptionally == true - thrown Exception - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEL" - kind CLIENT - errored true - errorEvent(IllegalStateException, "TestException") - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "DEL" - } - } - } - } - } - - def "cancel command before it finishes"() { - setup: - asyncCommands.setAutoFlushCommands(false) - def conds = new AsyncConditions() - RedisFuture redisFuture = asyncCommands.sadd("SKEY", "1", "2") - redisFuture.whenCompleteAsync({ - res, throwable -> - conds.evaluate { - assert throwable != null - assert throwable instanceof CancellationException - } - }) - - when: - boolean cancelSuccess = redisFuture.cancel(true) - asyncCommands.flushCommands() - - then: - conds.await() - cancelSuccess == true - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SADD" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "SADD" - "db.command.cancelled" true - } - } - } - } - } - - def "debug segfault command (returns void) with no argument should produce span"() { - setup: - asyncCommands.debugSegfault() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEBUG" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "DEBUG" - } - } - } - } - } - - - def "shutdown command (returns void) should produce a span"() { - setup: - asyncCommands.shutdown(false) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SHUTDOWN" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "SHUTDOWN" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-4.0/src/test/groovy/LettuceSyncClientTest.groovy b/instrumentation/lettuce/lettuce-4.0/src/test/groovy/LettuceSyncClientTest.groovy deleted file mode 100644 index 651c882be5..0000000000 --- a/instrumentation/lettuce/lettuce-4.0/src/test/groovy/LettuceSyncClientTest.groovy +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import com.lambdaworks.redis.ClientOptions -import com.lambdaworks.redis.RedisClient -import com.lambdaworks.redis.RedisConnectionException -import com.lambdaworks.redis.api.StatefulConnection -import com.lambdaworks.redis.api.sync.RedisCommands -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import redis.embedded.RedisServer -import spock.lang.Shared - -class LettuceSyncClientTest extends AgentTestRunner { - public static final String HOST = "localhost" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = new ClientOptions.Builder().autoReconnect(false).build() - - @Shared - int port - @Shared - int incorrectPort - @Shared - String dbAddr - @Shared - String dbAddrNonExistent - @Shared - String dbUriNonExistent - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - @Shared - Map testHashMap = [ - firstname: "John", - lastname : "Doe", - age : "53" - ] - - RedisClient redisClient - StatefulConnection connection - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - incorrectPort = PortUtils.randomOpenPort() - dbAddr = HOST + ":" + port + "/" + DB_INDEX - dbAddrNonExistent = HOST + ":" + incorrectPort + "/" + DB_INDEX - dbUriNonExistent = "redis://" + dbAddrNonExistent - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - redisServer.start() - connection = redisClient.connect() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - syncCommands.hmset("TESTHM", testHashMap) - - // 2 sets + 1 connect trace - TEST_WRITER.waitForTraces(3) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisServer.stop() - } - - def "connect"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - StatefulConnection connection = testConnectionClient.connect() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" HOST - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" port - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "CONNECT" - } - } - } - } - - cleanup: - connection.close() - } - - def "connect exception"() { - setup: - RedisClient testConnectionClient = RedisClient.create(dbUriNonExistent) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - testConnectionClient.connect() - - then: - thrown RedisConnectionException - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored true - errorEvent RedisConnectionException, String - attributes { - "${SemanticAttributes.NET_PEER_NAME.key()}" HOST - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" incorrectPort - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "CONNECT" - } - } - } - } - } - - def "set command"() { - setup: - String res = syncCommands.set("TESTSETKEY", "TESTSETVAL") - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "SET" - } - } - } - } - } - - def "get command"() { - setup: - String res = syncCommands.get("TESTKEY") - - expect: - res == "TESTVAL" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "GET" - } - } - } - } - } - - def "get non existent key command"() { - setup: - String res = syncCommands.get("NON_EXISTENT_KEY") - - expect: - res == null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "GET" - } - } - } - } - } - - def "command with no arguments"() { - setup: - def keyRetrieved = syncCommands.randomkey() - - expect: - keyRetrieved != null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "RANDOMKEY" - } - } - } - } - } - - def "list command"() { - setup: - long res = syncCommands.lpush("TESTLIST", "TESTLIST ELEMENT") - - expect: - res == 1 - assertTraces(1) { - trace(0, 1) { - span(0) { - name "LPUSH" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "LPUSH" - } - } - } - } - } - - def "hash set command"() { - setup: - def res = syncCommands.hmset("user", testHashMap) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "HMSET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "HMSET" - } - } - } - } - } - - def "hash getall command"() { - setup: - Map res = syncCommands.hgetall("TESTHM") - - expect: - res == testHashMap - assertTraces(1) { - trace(0, 1) { - span(0) { - name "HGETALL" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "HGETALL" - } - } - } - } - } - - def "debug segfault command (returns void) with no argument should produce span"() { - setup: - syncCommands.debugSegfault() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEBUG" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "DEBUG" - } - } - } - } - } - - def "shutdown command (returns void) should produce a span"() { - setup: - syncCommands.shutdown(false) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SHUTDOWN" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "SHUTDOWN" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy index 531b7b4e3b..644448f177 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceAsyncClientTest.groovy @@ -15,9 +15,9 @@ import io.lettuce.core.api.async.RedisAsyncCommands import io.lettuce.core.api.sync.RedisCommands import io.lettuce.core.codec.StringCodec import io.lettuce.core.protocol.AsyncCommand +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.concurrent.CancellationException import java.util.concurrent.CompletionException import java.util.concurrent.ExecutionException diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceReactiveClientTest.groovy b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceReactiveClientTest.groovy index 3c64d69693..2a42841d14 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceReactiveClientTest.groovy +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceReactiveClientTest.groovy @@ -3,17 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import io.lettuce.core.ClientOptions import io.lettuce.core.RedisClient import io.lettuce.core.api.StatefulConnection import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.sync.RedisCommands +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.function.Consumer import reactor.core.scheduler.Schedulers import redis.embedded.RedisServer diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy index d337adc1e9..be36bd58fa 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/groovy/LettuceSyncClientTest.groovy @@ -10,9 +10,9 @@ import io.lettuce.core.RedisClient import io.lettuce.core.RedisConnectionException import io.lettuce.core.api.StatefulConnection import io.lettuce.core.api.sync.RedisCommands +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.concurrent.CompletionException import redis.embedded.RedisServer import spock.lang.Shared diff --git a/instrumentation/lettuce/lettuce-5.0/lettuce-5.0.gradle b/instrumentation/lettuce/lettuce-5.0/lettuce-5.0.gradle deleted file mode 100644 index 2201aca7f0..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/lettuce-5.0.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.lettuce" - module = "lettuce-core" - versions = "[5.0.0.RELEASE,5.1.0.RELEASE)" - assertInverse = true - } -} - -dependencies { - compileOnly group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE' - - implementation project(':instrumentation:lettuce:lettuce-common') - - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' - testImplementation group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE' - testImplementation project(':instrumentation:reactor-3.1') -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/ConnectionFutureAdvice.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/ConnectionFutureAdvice.java deleted file mode 100644 index 140d7964b9..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/ConnectionFutureAdvice.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceConnectionDatabaseClientTracer.tracer; - -import io.lettuce.core.ConnectionFuture; -import io.lettuce.core.RedisURI; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import net.bytebuddy.asm.Advice; - -public class ConnectionFutureAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(1) RedisURI redisUri, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(redisUri, "CONNECT"); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Return ConnectionFuture connectionFuture, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - return; - } - connectionFuture.handleAsync(new LettuceAsyncBiFunction<>(span)); - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java deleted file mode 100644 index 3ed1ef7dcb..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAbstractDatabaseClientTracer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import io.lettuce.core.RedisURI; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.net.InetSocketAddress; - -public abstract class LettuceAbstractDatabaseClientTracer - extends DatabaseClientTracer { - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.lettuce"; - } - - @Override - protected String dbSystem(RedisURI connection) { - return DbSystem.REDIS; - } - - @Override - protected InetSocketAddress peerAddress(RedisURI redisUri) { - return new InetSocketAddress(redisUri.getHost(), redisUri.getPort()); - } - - @Override - public Span onConnection(Span span, RedisURI connection) { - if (connection != null && connection.getDatabase() != 0) { - span.setAttribute(SemanticAttributes.DB_REDIS_DATABASE_INDEX, connection.getDatabase()); - } - return super.onConnection(span, connection); - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java deleted file mode 100644 index 689655d0dc..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncBiFunction.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceDatabaseClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import java.util.concurrent.CancellationException; -import java.util.function.BiFunction; - -/** - * Callback class to close the span on an error or a success in the RedisFuture returned by the - * lettuce async API. - * - * @param the normal completion result - * @param the error - * @param the return type, should be null since nothing else should happen from tracing - * standpoint after the span is closed - */ -public class LettuceAsyncBiFunction - implements BiFunction { - - private final Span span; - - public LettuceAsyncBiFunction(Span span) { - this.span = span; - } - - @Override - public R apply(T t, Throwable throwable) { - if (throwable instanceof CancellationException) { - span.setAttribute("db.command.cancelled", true); - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - return null; - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsAdvice.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsAdvice.java deleted file mode 100644 index 6b5b329b2b..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsAdvice.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceDatabaseClientTracer.tracer; -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceInstrumentationUtil.expectsResponse; - -import io.lettuce.core.protocol.AsyncCommand; -import io.lettuce.core.protocol.RedisCommand; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import net.bytebuddy.asm.Advice; - -public class LettuceAsyncCommandsAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) RedisCommand command, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - span = tracer().startSpan(null, command); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Argument(0) RedisCommand command, - @Advice.Thrown Throwable throwable, - @Advice.Return AsyncCommand asyncCommand, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - return; - } - - // close spans on error or normal completion - if (expectsResponse(command)) { - asyncCommand.handleAsync(new LettuceAsyncBiFunction<>(span)); - } else { - tracer().end(span); - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsInstrumentation.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsInstrumentation.java deleted file mode 100644 index 069aabac3c..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncCommandsInstrumentation.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class LettuceAsyncCommandsInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("io.lettuce.core.AbstractRedisAsyncCommands"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("dispatch")) - .and(takesArgument(0, named("io.lettuce.core.protocol.RedisCommand"))), - LettuceAsyncCommandsAdvice.class.getName()); - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceClientInstrumentation.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceClientInstrumentation.java deleted file mode 100644 index 0b6aed94be..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceClientInstrumentation.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPrivate; -import static net.bytebuddy.matcher.ElementMatchers.nameEndsWith; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class LettuceClientInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("io.lettuce.core.RedisClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPrivate()) - .and(returns(named("io.lettuce.core.ConnectionFuture"))) - .and(nameStartsWith("connect")) - .and(nameEndsWith("Async")) - .and(takesArgument(1, named("io.lettuce.core.RedisURI"))), - ConnectionFutureAdvice.class.getName()); - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java deleted file mode 100644 index 6bd6ad8d6b..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceConnectionDatabaseClientTracer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -public class LettuceConnectionDatabaseClientTracer - extends LettuceAbstractDatabaseClientTracer { - private static final LettuceConnectionDatabaseClientTracer TRACER = - new LettuceConnectionDatabaseClientTracer(); - - public static LettuceConnectionDatabaseClientTracer tracer() { - return TRACER; - } - - @Override - protected String normalizeQuery(String query) { - return query; - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java deleted file mode 100644 index a6e96fecca..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDatabaseClientTracer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import io.lettuce.core.RedisURI; -import io.lettuce.core.protocol.RedisCommand; -import io.opentelemetry.javaagent.instrumentation.api.db.RedisCommandNormalizer; -import io.opentelemetry.javaagent.instrumentation.lettuce.LettuceArgSplitter; -import java.util.Collections; -import java.util.List; - -public class LettuceDatabaseClientTracer - extends LettuceAbstractDatabaseClientTracer> { - private static final LettuceDatabaseClientTracer TRACER = new LettuceDatabaseClientTracer(); - - public static LettuceDatabaseClientTracer tracer() { - return TRACER; - } - - private final RedisCommandNormalizer commandNormalizer = - new RedisCommandNormalizer("lettuce", "lettuce-5.0"); - - @Override - protected String spanName( - RedisURI connection, RedisCommand query, String normalizedQuery) { - return LettuceInstrumentationUtil.getCommandName(query); - } - - @Override - protected String normalizeQuery(RedisCommand redisCommand) { - String command = LettuceInstrumentationUtil.getCommandName(redisCommand); - List args = - redisCommand.getArgs() == null - ? Collections.emptyList() - : LettuceArgSplitter.splitArgs(redisCommand.getArgs().toCommandString()); - return commandNormalizer.normalize(command, args); - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationModule.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationModule.java deleted file mode 100644 index 7bae9b0c94..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationModule.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Arrays.asList; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class LettuceInstrumentationModule extends InstrumentationModule { - public LettuceInstrumentationModule() { - super("lettuce", "lettuce-5.0"); - } - - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return not(hasClassesNamed("io.lettuce.core.tracing.Tracing")); - } - - @Override - public List typeInstrumentations() { - return asList( - new LettuceAsyncCommandsInstrumentation(), - new LettuceClientInstrumentation(), - new LettuceReactiveCommandsInstrumentation()); - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationUtil.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationUtil.java deleted file mode 100644 index 2c19a24285..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceInstrumentationUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import io.lettuce.core.protocol.RedisCommand; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -public class LettuceInstrumentationUtil { - - public static final String[] NON_INSTRUMENTING_COMMAND_WORDS = - new String[] {"SHUTDOWN", "DEBUG", "OOM", "SEGFAULT"}; - - public static final Set nonInstrumentingCommands = - new HashSet<>(Arrays.asList(NON_INSTRUMENTING_COMMAND_WORDS)); - - /** - * Determines whether a redis command should finish its relevant span early (as soon as tags are - * added and the command is executed) because these commands have no return values/call backs, so - * we must close the span early in order to provide info for the users. - * - * @return false if the span should finish early (the command will not have a return value) - */ - public static boolean expectsResponse(RedisCommand command) { - String commandName = LettuceInstrumentationUtil.getCommandName(command); - return !nonInstrumentingCommands.contains(commandName); - } - - /** - * Retrieves the actual redis command name from a RedisCommand object. - * - * @param command the lettuce RedisCommand object - * @return the redis command as a string - */ - public static String getCommandName(RedisCommand command) { - String commandName = "Redis Command"; - if (command != null) { - - // get the redis command name (i.e. GET, SET, HMSET, etc) - if (command.getType() != null) { - commandName = command.getType().name().trim(); - } - } - return commandName; - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceReactiveCommandsInstrumentation.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceReactiveCommandsInstrumentation.java deleted file mode 100644 index 65e8836c0c..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceReactiveCommandsInstrumentation.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; - -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.nameEndsWith; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx.LettuceFluxCreationAdvice; -import io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx.LettuceMonoCreationAdvice; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class LettuceReactiveCommandsInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("io.lettuce.core.AbstractRedisReactiveCommands"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(named("createMono")) - .and(takesArgument(0, named("java.util.function.Supplier"))) - .and(returns(named("reactor.core.publisher.Mono"))), - LettuceMonoCreationAdvice.class.getName()); - transformers.put( - isMethod() - .and(nameStartsWith("create")) - .and(nameEndsWith("Flux")) - .and(isPublic()) - .and(takesArgument(0, named("java.util.function.Supplier"))) - .and(returns(named("reactor.core.publisher.Flux"))), - LettuceFluxCreationAdvice.class.getName()); - - return transformers; - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxCreationAdvice.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxCreationAdvice.java deleted file mode 100644 index 50b6920fce..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxCreationAdvice.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceInstrumentationUtil.expectsResponse; - -import io.lettuce.core.protocol.RedisCommand; -import java.util.function.Supplier; -import net.bytebuddy.asm.Advice; -import reactor.core.publisher.Flux; - -public class LettuceFluxCreationAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static RedisCommand extractCommandName( - @Advice.Argument(0) Supplier supplier) { - return supplier.get(); - } - - // if there is an exception thrown, then don't make spans - @Advice.OnMethodExit(suppress = Throwable.class) - public static void monitorSpan( - @Advice.Enter RedisCommand command, @Advice.Return(readOnly = false) Flux publisher) { - - boolean finishSpanOnClose = !expectsResponse(command); - LettuceFluxTerminationRunnable handler = - new LettuceFluxTerminationRunnable(command, finishSpanOnClose); - publisher = publisher.doOnSubscribe(handler.getOnSubscribeConsumer()); - // don't register extra callbacks to finish the spans if the command being instrumented is one - // of those that return - // Mono (In here a flux is created first and then converted to Mono) - if (!finishSpanOnClose) { - publisher = publisher.doOnEach(handler); - publisher = publisher.doOnCancel(handler); - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java deleted file mode 100644 index 66b4845938..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceDatabaseClientTracer.tracer; - -import io.lettuce.core.protocol.RedisCommand; -import io.opentelemetry.api.trace.Span; -import java.util.function.Consumer; -import org.reactivestreams.Subscription; -import org.slf4j.LoggerFactory; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Signal; -import reactor.core.publisher.SignalType; - -public class LettuceFluxTerminationRunnable implements Consumer>, Runnable { - - private Span span = null; - private int numResults = 0; - private FluxOnSubscribeConsumer onSubscribeConsumer; - - public LettuceFluxTerminationRunnable(RedisCommand command, boolean finishSpanOnClose) { - onSubscribeConsumer = new FluxOnSubscribeConsumer(this, command, finishSpanOnClose); - } - - public FluxOnSubscribeConsumer getOnSubscribeConsumer() { - return onSubscribeConsumer; - } - - private void finishSpan(boolean isCommandCancelled, Throwable throwable) { - if (span != null) { - span.setAttribute("db.command.results.count", numResults); - if (isCommandCancelled) { - span.setAttribute("db.command.cancelled", true); - } - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - } else { - LoggerFactory.getLogger(Flux.class) - .error( - "Failed to finish this.span, LettuceFluxTerminationRunnable cannot find this.span " - + "because it probably wasn't started."); - } - } - - @Override - public void accept(Signal signal) { - if (SignalType.ON_COMPLETE.equals(signal.getType()) - || SignalType.ON_ERROR.equals(signal.getType())) { - finishSpan(false, signal.getThrowable()); - } else if (SignalType.ON_NEXT.equals(signal.getType())) { - ++numResults; - } - } - - @Override - public void run() { - finishSpan(true, null); - } - - public static class FluxOnSubscribeConsumer implements Consumer { - - private final LettuceFluxTerminationRunnable owner; - private final RedisCommand command; - private final boolean finishSpanOnClose; - - public FluxOnSubscribeConsumer( - LettuceFluxTerminationRunnable owner, - RedisCommand command, - boolean finishSpanOnClose) { - this.owner = owner; - this.command = command; - this.finishSpanOnClose = finishSpanOnClose; - } - - @Override - public void accept(Subscription subscription) { - owner.span = tracer().startSpan(null, command); - if (finishSpanOnClose) { - tracer().end(owner.span); - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceMonoCreationAdvice.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceMonoCreationAdvice.java deleted file mode 100644 index 0920070cf4..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceMonoCreationAdvice.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceInstrumentationUtil.expectsResponse; - -import io.lettuce.core.protocol.RedisCommand; -import java.util.function.Supplier; -import net.bytebuddy.asm.Advice; -import reactor.core.publisher.Mono; - -public class LettuceMonoCreationAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static RedisCommand extractCommandName( - @Advice.Argument(0) Supplier supplier) { - return supplier.get(); - } - - // throwables wouldn't matter here, because no spans have been started due to redis command not - // being run until the user subscribes to the Mono publisher - @Advice.OnMethodExit(suppress = Throwable.class) - public static void monitorSpan( - @Advice.Enter RedisCommand command, @Advice.Return(readOnly = false) Mono publisher) { - boolean finishSpanOnClose = !expectsResponse(command); - LettuceMonoDualConsumer mdc = new LettuceMonoDualConsumer(command, finishSpanOnClose); - publisher = publisher.doOnSubscribe(mdc); - // register the call back to close the span only if necessary - if (!finishSpanOnClose) { - publisher = publisher.doOnSuccessOrError(mdc); - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceMonoDualConsumer.java b/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceMonoDualConsumer.java deleted file mode 100644 index 136ecbb0e3..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceMonoDualConsumer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.rx; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.v5_0.LettuceDatabaseClientTracer.tracer; - -import io.lettuce.core.protocol.RedisCommand; -import io.opentelemetry.api.trace.Span; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import org.slf4j.LoggerFactory; -import reactor.core.publisher.Mono; - -public class LettuceMonoDualConsumer implements Consumer, BiConsumer { - - private Span span = null; - private final RedisCommand command; - private final boolean finishSpanOnClose; - - public LettuceMonoDualConsumer(RedisCommand command, boolean finishSpanOnClose) { - this.command = command; - this.finishSpanOnClose = finishSpanOnClose; - } - - @Override - public void accept(R r) { - span = tracer().startSpan(null, command); - if (finishSpanOnClose) { - tracer().end(span); - } - } - - @Override - public void accept(T t, Throwable throwable) { - if (span != null) { - if (throwable == null) { - tracer().end(span); - } else { - tracer().endExceptionally(span, throwable); - } - } else { - LoggerFactory.getLogger(Mono.class) - .error( - "Failed to finish this.span, BiConsumer cannot find this.span because " - + "it probably wasn't started."); - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceAsyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceAsyncClientTest.groovy deleted file mode 100644 index 644448f177..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceAsyncClientTest.groovy +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.lettuce.core.ClientOptions -import io.lettuce.core.ConnectionFuture -import io.lettuce.core.RedisClient -import io.lettuce.core.RedisFuture -import io.lettuce.core.RedisURI -import io.lettuce.core.api.StatefulConnection -import io.lettuce.core.api.async.RedisAsyncCommands -import io.lettuce.core.api.sync.RedisCommands -import io.lettuce.core.codec.StringCodec -import io.lettuce.core.protocol.AsyncCommand -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.concurrent.CancellationException -import java.util.concurrent.CompletionException -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import java.util.function.BiConsumer -import java.util.function.BiFunction -import java.util.function.Consumer -import java.util.function.Function -import redis.embedded.RedisServer -import spock.lang.Shared -import spock.util.concurrent.AsyncConditions - -class LettuceAsyncClientTest extends AgentTestRunner { - public static final String PEER_NAME = "localhost" - public static final String PEER_IP = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - int port - @Shared - int incorrectPort - @Shared - String dbAddr - @Shared - String dbAddrNonExistent - @Shared - String dbUriNonExistent - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - @Shared - Map testHashMap = [ - firstname: "John", - lastname : "Doe", - age : "53" - ] - - RedisClient redisClient - StatefulConnection connection - RedisAsyncCommands asyncCommands - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - incorrectPort = PortUtils.randomOpenPort() - dbAddr = PEER_NAME + ":" + port + "/" + DB_INDEX - dbAddrNonExistent = PEER_NAME + ":" + incorrectPort + "/" + DB_INDEX - dbUriNonExistent = "redis://" + dbAddrNonExistent - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + PEER_NAME) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - println "Using redis: $redisServer.args" - redisServer.start() - redisClient.setOptions(CLIENT_OPTIONS) - - connection = redisClient.connect() - asyncCommands = connection.async() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - - // 1 set + 1 connect trace - TEST_WRITER.waitForTraces(2) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisServer.stop() - } - - def "connect using get on ConnectionFuture"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - ConnectionFuture connectionFuture = testConnectionClient.connectAsync(StringCodec.UTF8, - new RedisURI(PEER_NAME, port, 3, TimeUnit.SECONDS)) - StatefulConnection connection = connectionFuture.get() - - then: - connection != null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" PEER_NAME - "$SemanticAttributes.NET_PEER_IP.key" PEER_IP - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "CONNECT" - } - } - } - } - - cleanup: - connection.close() - } - - def "connect exception inside the connection future"() { - setup: - RedisClient testConnectionClient = RedisClient.create(dbUriNonExistent) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - ConnectionFuture connectionFuture = testConnectionClient.connectAsync(StringCodec.UTF8, - new RedisURI(PEER_NAME, incorrectPort, 3, TimeUnit.SECONDS)) - StatefulConnection connection = connectionFuture.get() - - then: - connection == null - thrown ExecutionException - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored true - errorEvent CompletionException, String - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" PEER_NAME - "$SemanticAttributes.NET_PEER_IP.key" PEER_IP - "$SemanticAttributes.NET_PEER_PORT.key" incorrectPort - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "CONNECT" - } - } - } - } - } - - def "set command using Future get with timeout"() { - setup: - RedisFuture redisFuture = asyncCommands.set("TESTSETKEY", "TESTSETVAL") - String res = redisFuture.get(3, TimeUnit.SECONDS) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SET TESTSETKEY ?" - } - } - } - } - } - - def "get command chained with thenAccept"() { - setup: - def conds = new AsyncConditions() - Consumer consumer = new Consumer() { - @Override - void accept(String res) { - conds.evaluate { - assert res == "TESTVAL" - } - } - } - - when: - RedisFuture redisFuture = asyncCommands.get("TESTKEY") - redisFuture.thenAccept(consumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET TESTKEY" - } - } - } - } - } - - // to make sure instrumentation's chained completion stages won't interfere with user's, while still - // recording metrics - def "get non existent key command with handleAsync and chained with thenApply"() { - setup: - def conds = new AsyncConditions() - String successStr = "KEY MISSING" - BiFunction firstStage = new BiFunction() { - @Override - String apply(String res, Throwable throwable) { - conds.evaluate { - assert res == null - assert throwable == null - } - return (res == null ? successStr : res) - } - } - Function secondStage = new Function() { - @Override - Object apply(String input) { - conds.evaluate { - assert input == successStr - } - return null - } - } - - when: - RedisFuture redisFuture = asyncCommands.get("NON_EXISTENT_KEY") - redisFuture.handleAsync(firstStage).thenApply(secondStage) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET NON_EXISTENT_KEY" - } - } - } - } - } - - def "command with no arguments using a biconsumer"() { - setup: - def conds = new AsyncConditions() - BiConsumer biConsumer = new BiConsumer() { - @Override - void accept(String keyRetrieved, Throwable throwable) { - conds.evaluate { - assert keyRetrieved != null - } - } - } - - when: - RedisFuture redisFuture = asyncCommands.randomkey() - redisFuture.whenCompleteAsync(biConsumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "RANDOMKEY" - } - } - } - } - } - - def "hash set and then nest apply to hash getall"() { - setup: - def conds = new AsyncConditions() - - when: - RedisFuture hmsetFuture = asyncCommands.hmset("TESTHM", testHashMap) - hmsetFuture.thenApplyAsync(new Function() { - @Override - Object apply(String setResult) { - conds.evaluate { - assert setResult == "OK" - } - RedisFuture> hmGetAllFuture = asyncCommands.hgetall("TESTHM") - hmGetAllFuture.exceptionally(new Function>() { - @Override - Map apply(Throwable throwable) { - println("unexpected:" + throwable.toString()) - throwable.printStackTrace() - assert false - return null - } - }) - hmGetAllFuture.thenAccept(new Consumer>() { - @Override - void accept(Map hmGetAllResult) { - conds.evaluate { - assert testHashMap == hmGetAllResult - } - } - }) - return null - } - }) - - then: - conds.await() - assertTraces(2) { - trace(0, 1) { - span(0) { - name "HMSET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "HMSET TESTHM firstname ? lastname ? age ?" - } - } - } - trace(1, 1) { - span(0) { - name "HGETALL" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "HGETALL TESTHM" - } - } - } - } - } - - def "command completes exceptionally"() { - setup: - // turn off auto flush to complete the command exceptionally manually - asyncCommands.setAutoFlushCommands(false) - def conds = new AsyncConditions() - RedisFuture redisFuture = asyncCommands.del("key1", "key2") - boolean completedExceptionally = ((AsyncCommand) redisFuture).completeExceptionally(new IllegalStateException("TestException")) - redisFuture.exceptionally({ - throwable -> - conds.evaluate { - assert throwable != null - assert throwable instanceof IllegalStateException - assert throwable.getMessage() == "TestException" - } - throw throwable - }) - - when: - // now flush and execute the command - asyncCommands.flushCommands() - redisFuture.get() - - then: - conds.await() - completedExceptionally == true - thrown Exception - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEL" - kind CLIENT - errored true - errorEvent(IllegalStateException, "TestException") - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "DEL key1 key2" - } - } - } - } - } - - def "cancel command before it finishes"() { - setup: - asyncCommands.setAutoFlushCommands(false) - def conds = new AsyncConditions() - RedisFuture redisFuture = asyncCommands.sadd("SKEY", "1", "2") - redisFuture.whenCompleteAsync({ - res, throwable -> - conds.evaluate { - assert throwable != null - assert throwable instanceof CancellationException - } - }) - - when: - boolean cancelSuccess = redisFuture.cancel(true) - asyncCommands.flushCommands() - - then: - conds.await() - cancelSuccess == true - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SADD" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SADD SKEY ? ?" - "db.command.cancelled" true - } - } - } - } - } - - def "debug segfault command (returns void) with no argument should produce span"() { - setup: - asyncCommands.debugSegfault() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEBUG" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "DEBUG SEGFAULT" - } - } - } - } - } - - - def "shutdown command (returns void) should produce a span"() { - setup: - asyncCommands.shutdown(false) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SHUTDOWN" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SHUTDOWN NOSAVE" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceReactiveClientTest.groovy b/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceReactiveClientTest.groovy deleted file mode 100644 index 2a42841d14..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceReactiveClientTest.groovy +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.lettuce.core.ClientOptions -import io.lettuce.core.RedisClient -import io.lettuce.core.api.StatefulConnection -import io.lettuce.core.api.reactive.RedisReactiveCommands -import io.lettuce.core.api.sync.RedisCommands -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.function.Consumer -import reactor.core.scheduler.Schedulers -import redis.embedded.RedisServer -import spock.lang.Shared -import spock.util.concurrent.AsyncConditions - -class LettuceReactiveClientTest extends AgentTestRunner { - public static final String PEER_HOST = "localhost" - public static final String PEER_IP = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - RedisClient redisClient - StatefulConnection connection - RedisReactiveCommands reactiveCommands - RedisCommands syncCommands - - def setupSpec() { - int port = PortUtils.randomOpenPort() - String dbAddr = PEER_HOST + ":" + port + "/" + DB_INDEX - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + PEER_HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - println "Using redis: $redisServer.args" - redisServer.start() - redisClient.setOptions(CLIENT_OPTIONS) - - connection = redisClient.connect() - reactiveCommands = connection.reactive() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - - // 1 set + 1 connect trace - TEST_WRITER.waitForTraces(2) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisClient.shutdown() - redisServer.stop() - } - - def "set command with subscribe on a defined consumer"() { - setup: - def conds = new AsyncConditions() - Consumer consumer = new Consumer() { - @Override - void accept(String res) { - conds.evaluate { - assert res == "OK" - } - } - } - - when: - reactiveCommands.set("TESTSETKEY", "TESTSETVAL").subscribe(consumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SET TESTSETKEY ?" - } - } - } - } - } - - def "get command with lambda function"() { - setup: - def conds = new AsyncConditions() - - when: - reactiveCommands.get("TESTKEY").subscribe { res -> conds.evaluate { assert res == "TESTVAL" } } - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET TESTKEY" - } - } - } - } - } - - // to make sure instrumentation's chained completion stages won't interfere with user's, while still - // recording metrics - def "get non existent key command"() { - setup: - def conds = new AsyncConditions() - final defaultVal = "NOT THIS VALUE" - - when: - reactiveCommands.get("NON_EXISTENT_KEY").defaultIfEmpty(defaultVal).subscribe { - res -> - conds.evaluate { - assert res == defaultVal - } - } - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET NON_EXISTENT_KEY" - } - } - } - } - - } - - def "command with no arguments"() { - setup: - def conds = new AsyncConditions() - - when: - reactiveCommands.randomkey().subscribe { - res -> - conds.evaluate { - assert res == "TESTKEY" - } - } - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "RANDOMKEY" - } - } - } - } - } - - def "command flux publisher "() { - setup: - reactiveCommands.command().subscribe() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "COMMAND" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "COMMAND" - "db.command.results.count" 157 - } - } - } - } - } - - def "command cancel after 2 on flux publisher "() { - setup: - reactiveCommands.command().take(2).subscribe() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "COMMAND" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "COMMAND" - "db.command.cancelled" true - "db.command.results.count" 2 - } - } - } - } - } - - def "non reactive command should not produce span"() { - setup: - String res = null - - when: - res = reactiveCommands.digest(null) - - then: - res != null - TEST_WRITER.traces.size() == 0 - } - - def "debug segfault command (returns mono void) with no argument should produce span"() { - setup: - reactiveCommands.debugSegfault().subscribe() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEBUG" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "DEBUG SEGFAULT" - } - } - } - } - } - - def "shutdown command (returns void) with argument should produce span"() { - setup: - reactiveCommands.shutdown(false).subscribe() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SHUTDOWN" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SHUTDOWN NOSAVE" - } - } - } - } - } - - def "blocking subscriber"() { - when: - runUnderTrace("test-parent") { - reactiveCommands.set("a", "1") - .then(reactiveCommands.get("a")) - .block() - } - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "test-parent" - errored false - attributes { - } - } - span(1) { - name "SET" - kind CLIENT - errored false - childOf span(0) - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SET a ?" - } - } - span(2) { - name "GET" - kind CLIENT - errored false - childOf span(0) - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET a" - } - } - } - } - } - - def "async subscriber"() { - when: - runUnderTrace("test-parent") { - reactiveCommands.set("a", "1") - .then(reactiveCommands.get("a")) - .subscribe() - } - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "test-parent" - errored false - attributes { - } - } - span(1) { - name "SET" - kind CLIENT - errored false - childOf span(0) - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SET a ?" - } - } - span(2) { - name "GET" - kind CLIENT - errored false - childOf span(0) - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET a" - } - } - } - } - } - - def "async subscriber with specific thread pool"() { - when: - runUnderTrace("test-parent") { - reactiveCommands.set("a", "1") - .then(reactiveCommands.get("a")) - .subscribeOn(Schedulers.elastic()) - .subscribe() - } - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "test-parent" - errored false - attributes { - } - } - span(1) { - name "SET" - kind CLIENT - errored false - childOf span(0) - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SET a ?" - } - } - span(2) { - name "GET" - kind CLIENT - errored false - childOf span(0) - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET a" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceSyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceSyncClientTest.groovy deleted file mode 100644 index be36bd58fa..0000000000 --- a/instrumentation/lettuce/lettuce-5.0/src/test/groovy/LettuceSyncClientTest.groovy +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.lettuce.core.ClientOptions -import io.lettuce.core.RedisClient -import io.lettuce.core.RedisConnectionException -import io.lettuce.core.api.StatefulConnection -import io.lettuce.core.api.sync.RedisCommands -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.concurrent.CompletionException -import redis.embedded.RedisServer -import spock.lang.Shared - -class LettuceSyncClientTest extends AgentTestRunner { - public static final String PEER_NAME = "localhost" - public static final String PEER_IP = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - int port - @Shared - int incorrectPort - @Shared - String dbAddr - @Shared - String dbAddrNonExistent - @Shared - String dbUriNonExistent - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - @Shared - Map testHashMap = [ - firstname: "John", - lastname : "Doe", - age : "53" - ] - - RedisClient redisClient - StatefulConnection connection - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - incorrectPort = PortUtils.randomOpenPort() - dbAddr = PEER_NAME + ":" + port + "/" + DB_INDEX - dbAddrNonExistent = PEER_NAME + ":" + incorrectPort + "/" + DB_INDEX - dbUriNonExistent = "redis://" + dbAddrNonExistent - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + PEER_NAME) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - redisServer.start() - connection = redisClient.connect() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - syncCommands.hmset("TESTHM", testHashMap) - - // 2 sets + 1 connect trace - TEST_WRITER.waitForTraces(3) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisServer.stop() - } - - def "connect"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - StatefulConnection connection = testConnectionClient.connect() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" PEER_NAME - "$SemanticAttributes.NET_PEER_IP.key" PEER_IP - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "CONNECT" - } - } - } - } - - cleanup: - connection.close() - } - - def "connect exception"() { - setup: - RedisClient testConnectionClient = RedisClient.create(dbUriNonExistent) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - testConnectionClient.connect() - - then: - thrown RedisConnectionException - assertTraces(1) { - trace(0, 1) { - span(0) { - name "CONNECT" - kind CLIENT - errored true - errorEvent CompletionException, String - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" PEER_NAME - "$SemanticAttributes.NET_PEER_IP.key" PEER_IP - "$SemanticAttributes.NET_PEER_PORT.key" incorrectPort - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "CONNECT" - } - } - } - } - } - - def "set command"() { - setup: - String res = syncCommands.set("TESTSETKEY", "TESTSETVAL") - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SET TESTSETKEY ?" - } - } - } - } - } - - def "get command"() { - setup: - String res = syncCommands.get("TESTKEY") - - expect: - res == "TESTVAL" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET TESTKEY" - } - } - } - } - } - - def "get non existent key command"() { - setup: - String res = syncCommands.get("NON_EXISTENT_KEY") - - expect: - res == null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "GET NON_EXISTENT_KEY" - } - } - } - } - } - - def "command with no arguments"() { - setup: - def keyRetrieved = syncCommands.randomkey() - - expect: - keyRetrieved != null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "RANDOMKEY" - } - } - } - } - } - - def "list command"() { - setup: - long res = syncCommands.lpush("TESTLIST", "TESTLIST ELEMENT") - - expect: - res == 1 - assertTraces(1) { - trace(0, 1) { - span(0) { - name "LPUSH" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "LPUSH TESTLIST ?" - } - } - } - } - } - - def "hash set command"() { - setup: - def res = syncCommands.hmset("user", testHashMap) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "HMSET" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "HMSET user firstname ? lastname ? age ?" - } - } - } - } - } - - def "hash getall command"() { - setup: - Map res = syncCommands.hgetall("TESTHM") - - expect: - res == testHashMap - assertTraces(1) { - trace(0, 1) { - span(0) { - name "HGETALL" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "HGETALL TESTHM" - } - } - } - } - } - - def "debug segfault command (returns void) with no argument should produce span"() { - setup: - syncCommands.debugSegfault() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "DEBUG" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "DEBUG SEGFAULT" - } - } - } - } - } - - def "shutdown command (returns void) should produce a span"() { - setup: - syncCommands.shutdown(false) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SHUTDOWN" - kind CLIENT - errored false - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.DB_STATEMENT.key" "SHUTDOWN NOSAVE" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy index 5ad8345a65..77da33e0d3 100644 --- a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy +++ b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy @@ -16,9 +16,9 @@ import io.lettuce.core.api.StatefulConnection import io.lettuce.core.api.async.RedisAsyncCommands import io.lettuce.core.api.sync.RedisCommands import io.lettuce.core.codec.StringCodec +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.concurrent.ExecutionException import java.util.concurrent.TimeUnit import java.util.function.BiConsumer diff --git a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy index 7e7c22da8c..15b592c025 100644 --- a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy +++ b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy @@ -5,17 +5,17 @@ package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1 -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import io.lettuce.core.ClientOptions import io.lettuce.core.RedisClient import io.lettuce.core.api.StatefulConnection import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.sync.RedisCommands +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.function.Consumer import reactor.core.scheduler.Schedulers import redis.embedded.RedisServer diff --git a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy index 4a57cf7992..197a0bc8da 100644 --- a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy +++ b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy @@ -9,9 +9,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import io.lettuce.core.ClientOptions import io.lettuce.core.RedisClient +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import redis.embedded.RedisServer import spock.lang.Shared diff --git a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy index ca19ecf9f4..68444efe6c 100644 --- a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy +++ b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy @@ -14,9 +14,9 @@ import io.lettuce.core.RedisConnectionException import io.lettuce.core.ScriptOutputType import io.lettuce.core.api.StatefulConnection import io.lettuce.core.api.sync.RedisCommands +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import redis.embedded.RedisServer import spock.lang.Shared diff --git a/instrumentation/lettuce/lettuce-5.1/lettuce-5.1.gradle b/instrumentation/lettuce/lettuce-5.1/lettuce-5.1.gradle deleted file mode 100644 index d9a6726c27..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/lettuce-5.1.gradle +++ /dev/null @@ -1,23 +0,0 @@ -apply from: "${rootDir}/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.lettuce" - module = "lettuce-core" - versions = "[5.1.0.RELEASE,6.0.0.RELEASE)" - assertInverse = true - } -} - -dependencies { - library group: 'io.lettuce', name: 'lettuce-core', version: '5.1.0.RELEASE' - - implementation project(':instrumentation:lettuce:lettuce-common') - - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' - // Only 5.2+ will have command arguments in the db.statement tag. - testLibrary group: 'io.lettuce', name: 'lettuce-core', version: '5.2.0.RELEASE' - testImplementation project(':instrumentation:reactor-3.1') - - latestDepTestLibrary group: 'io.lettuce', name: 'lettuce-core', version: '5.+' -} diff --git a/instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceInstrumentationModule.java b/instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceInstrumentationModule.java deleted file mode 100644 index 6a4277b9dc..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceInstrumentationModule.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.lettuce.core.resource.DefaultClientResources; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class LettuceInstrumentationModule extends InstrumentationModule { - - public LettuceInstrumentationModule() { - super("lettuce", "lettuce-5.1"); - } - - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return hasClassesNamed("io.lettuce.core.tracing.Tracing"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new DefaultClientResourcesInstrumentation()); - } - - public static class DefaultClientResourcesInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("io.lettuce.core.resource.DefaultClientResources"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(isStatic()).and(named("builder")), - LettuceInstrumentationModule.class.getName() + "$DefaultClientResourcesAdvice"); - } - } - - public static class DefaultClientResourcesAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void methodEnter(@Advice.Return DefaultClientResources.Builder builder) { - builder.tracing(OpenTelemetryTracing.INSTANCE); - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/OpenTelemetryTracing.java b/instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/OpenTelemetryTracing.java deleted file mode 100644 index 039a2f8990..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/OpenTelemetryTracing.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1; - -import static io.opentelemetry.javaagent.instrumentation.lettuce.LettuceArgSplitter.splitArgs; - -import io.lettuce.core.tracing.TraceContext; -import io.lettuce.core.tracing.TraceContextProvider; -import io.lettuce.core.tracing.Tracer; -import io.lettuce.core.tracing.TracerProvider; -import io.lettuce.core.tracing.Tracing; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils.SpanAttributeSetter; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import io.opentelemetry.javaagent.instrumentation.api.db.RedisCommandNormalizer; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import org.checkerframework.checker.nullness.qual.Nullable; - -public enum OpenTelemetryTracing implements Tracing { - INSTANCE; - - private static final io.opentelemetry.api.trace.Tracer TRACER = - OpenTelemetry.getGlobalTracer("io.opentelemetry.auto.lettuce-5.1"); - - public static io.opentelemetry.api.trace.Tracer tracer() { - return TRACER; - } - - private static final RedisCommandNormalizer commandNormalizer = - new RedisCommandNormalizer("lettuce", "lettuce-5.1"); - - @Override - public TracerProvider getTracerProvider() { - return OpenTelemetryTracerProvider.INSTANCE; - } - - @Override - public TraceContextProvider initialTraceContextProvider() { - return OpenTelemetryTraceContextProvider.INSTANCE; - } - - @Override - public boolean isEnabled() { - return true; - } - - // Added in lettuce 5.2 - // @Override - public boolean includeCommandArgsInSpanTags() { - return true; - } - - @Override - public Endpoint createEndpoint(SocketAddress socketAddress) { - if (socketAddress instanceof InetSocketAddress) { - InetSocketAddress address = (InetSocketAddress) socketAddress; - - String ip = address.getAddress() == null ? null : address.getAddress().getHostAddress(); - return new OpenTelemetryEndpoint(ip, address.getPort(), address.getHostString()); - } - return null; - } - - private enum OpenTelemetryTracerProvider implements TracerProvider { - INSTANCE; - - private final Tracer openTelemetryTracer = new OpenTelemetryTracer(); - - @Override - public Tracer getTracer() { - return openTelemetryTracer; - } - } - - private enum OpenTelemetryTraceContextProvider implements TraceContextProvider { - INSTANCE; - - @Override - public TraceContext getTraceContext() { - return new OpenTelemetryTraceContext(); - } - } - - private static class OpenTelemetryTraceContext implements TraceContext { - private final Context context; - - OpenTelemetryTraceContext() { - this.context = Context.current(); - } - - public Context getSpanContext() { - return context; - } - } - - private static class OpenTelemetryEndpoint implements Endpoint { - @Nullable final String ip; - final int port; - @Nullable final String name; - - OpenTelemetryEndpoint(@Nullable String ip, int port, @Nullable String name) { - this.ip = ip; - this.port = port; - this.name = name; - } - } - - private static class OpenTelemetryTracer extends Tracer { - - OpenTelemetryTracer() {} - - @Override - public OpenTelemetrySpan nextSpan() { - return new OpenTelemetrySpan(Context.current()); - } - - @Override - public OpenTelemetrySpan nextSpan(TraceContext traceContext) { - if (!(traceContext instanceof OpenTelemetryTraceContext)) { - return nextSpan(); - } - - Context context = ((OpenTelemetryTraceContext) traceContext).getSpanContext(); - - return new OpenTelemetrySpan(context); - } - } - - // The order that callbacks will be called in or which thread they are called from is not well - // defined. We go ahead and buffer all data until we know we have a span. This implementation is - // particularly safe, synchronizing all accesses. Relying on implementation details would allow - // reducing synchronization but the impact should be minimal. - private static class OpenTelemetrySpan extends Tracer.Span { - private final SpanBuilder spanBuilder; - - @Nullable private String name; - - @Nullable private List events; - - @Nullable private Throwable error; - - @Nullable private Span span; - - @Nullable private String args; - - OpenTelemetrySpan(Context parent) { - // Name will be updated later, we create with an arbitrary one here to store other data before - // the span starts. - spanBuilder = - TRACER - .spanBuilder("redis") - .setSpanKind(Kind.CLIENT) - .setParent(parent) - .setAttribute(SemanticAttributes.DB_SYSTEM, DbSystem.REDIS); - } - - @Override - public synchronized Tracer.Span name(String name) { - if (span != null) { - span.updateName(name); - } - - this.name = name; - - return this; - } - - @Override - public synchronized Tracer.Span remoteEndpoint(Endpoint endpoint) { - if (endpoint instanceof OpenTelemetryEndpoint) { - if (span != null) { - fillEndpoint(span::setAttribute, (OpenTelemetryEndpoint) endpoint); - } else { - fillEndpoint(spanBuilder::setAttribute, (OpenTelemetryEndpoint) endpoint); - } - } - return this; - } - - @Override - public synchronized Tracer.Span start() { - span = spanBuilder.startSpan(); - if (name != null) { - span.updateName(name); - } - - if (events != null) { - for (int i = 0; i < events.size(); i += 2) { - span.addEvent((String) events.get(i), (Instant) events.get(i + 1)); - } - events = null; - } - - if (error != null) { - span.setStatus(StatusCode.ERROR); - span.recordException(error); - error = null; - } - - return this; - } - - @Override - public synchronized Tracer.Span annotate(String value) { - if (span != null) { - span.addEvent(value); - } else { - if (events == null) { - events = new ArrayList<>(); - } - events.add(value); - events.add(Instant.now()); - } - return this; - } - - @Override - public synchronized Tracer.Span tag(String key, String value) { - if (key.equals("redis.args")) { - args = value; - return this; - } - if (span != null) { - span.setAttribute(key, value); - } else { - spanBuilder.setAttribute(key, value); - } - return this; - } - - @Override - public synchronized Tracer.Span error(Throwable throwable) { - if (span != null) { - span.recordException(throwable); - } else { - this.error = throwable; - } - return this; - } - - @Override - public synchronized void finish() { - if (span != null) { - if (name != null) { - String statement = commandNormalizer.normalize(name, splitArgs(args)); - span.setAttribute(SemanticAttributes.DB_STATEMENT, statement); - } - span.end(); - } - } - - private static void fillEndpoint(SpanAttributeSetter span, OpenTelemetryEndpoint endpoint) { - span.setAttribute(SemanticAttributes.NET_TRANSPORT, "IP.TCP"); - NetPeerUtils.setNetPeer(span, endpoint.name, endpoint.ip, endpoint.port); - - StringBuilder redisUrl = - new StringBuilder("redis://").append(endpoint.name != null ? endpoint.name : endpoint.ip); - if (endpoint.port > 0) { - redisUrl.append(":").append(endpoint.port); - } - - span.setAttribute(SemanticAttributes.DB_CONNECTION_STRING, redisUrl.toString()); - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy deleted file mode 100644 index 77da33e0d3..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.groovy +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1 - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.lettuce.core.ClientOptions -import io.lettuce.core.ConnectionFuture -import io.lettuce.core.RedisClient -import io.lettuce.core.RedisFuture -import io.lettuce.core.RedisURI -import io.lettuce.core.api.StatefulConnection -import io.lettuce.core.api.async.RedisAsyncCommands -import io.lettuce.core.api.sync.RedisCommands -import io.lettuce.core.codec.StringCodec -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import java.util.function.BiConsumer -import java.util.function.BiFunction -import java.util.function.Consumer -import java.util.function.Function -import redis.embedded.RedisServer -import spock.lang.Shared -import spock.util.concurrent.AsyncConditions - -class LettuceAsyncClientTest extends AgentTestRunner { - public static final String HOST = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - int port - @Shared - int incorrectPort - @Shared - String dbAddr - @Shared - String dbAddrNonExistent - @Shared - String dbUriNonExistent - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - @Shared - Map testHashMap = [ - firstname: "John", - lastname : "Doe", - age : "53" - ] - - RedisClient redisClient - StatefulConnection connection - RedisAsyncCommands asyncCommands - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - incorrectPort = PortUtils.randomOpenPort() - dbAddr = HOST + ":" + port + "/" + DB_INDEX - dbAddrNonExistent = HOST + ":" + incorrectPort + "/" + DB_INDEX - dbUriNonExistent = "redis://" + dbAddrNonExistent - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - println "Using redis: $redisServer.args" - redisServer.start() - redisClient.setOptions(CLIENT_OPTIONS) - - connection = redisClient.connect() - asyncCommands = connection.async() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - - // 1 set - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisServer.stop() - } - - def "connect using get on ConnectionFuture"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - ConnectionFuture connectionFuture = testConnectionClient.connectAsync(StringCodec.UTF8, - new RedisURI(HOST, port, 3, TimeUnit.SECONDS)) - StatefulConnection connection = connectionFuture.get() - - then: - connection != null - // Lettuce tracing does not trace connect - assertTraces(0) {} - - cleanup: - connection.close() - } - - def "connect exception inside the connection future"() { - setup: - RedisClient testConnectionClient = RedisClient.create(dbUriNonExistent) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - ConnectionFuture connectionFuture = testConnectionClient.connectAsync(StringCodec.UTF8, - new RedisURI(HOST, incorrectPort, 3, TimeUnit.SECONDS)) - StatefulConnection connection = connectionFuture.get() - - then: - connection == null - thrown ExecutionException - // Lettuce tracing does not trace connect - assertTraces(0) {} - } - - def "set command using Future get with timeout"() { - setup: - RedisFuture redisFuture = asyncCommands.set("TESTSETKEY", "TESTSETVAL") - String res = redisFuture.get(3, TimeUnit.SECONDS) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "get command chained with thenAccept"() { - setup: - def conds = new AsyncConditions() - Consumer consumer = new Consumer() { - @Override - void accept(String res) { - conds.evaluate { - assert res == "TESTVAL" - } - } - } - - when: - RedisFuture redisFuture = asyncCommands.get("TESTKEY") - redisFuture.thenAccept(consumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET TESTKEY" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - // to make sure instrumentation's chained completion stages won't interfere with user's, while still - // recording metrics - def "get non existent key command with handleAsync and chained with thenApply"() { - setup: - def conds = new AsyncConditions() - String successStr = "KEY MISSING" - BiFunction firstStage = new BiFunction() { - @Override - String apply(String res, Throwable throwable) { - conds.evaluate { - assert res == null - assert throwable == null - } - return (res == null ? successStr : res) - } - } - Function secondStage = new Function() { - @Override - Object apply(String input) { - conds.evaluate { - assert input == successStr - } - return null - } - } - - when: - RedisFuture redisFuture = asyncCommands.get("NON_EXISTENT_KEY") - redisFuture.handleAsync(firstStage).thenApply(secondStage) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET NON_EXISTENT_KEY" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "command with no arguments using a biconsumer"() { - setup: - def conds = new AsyncConditions() - BiConsumer biConsumer = new BiConsumer() { - @Override - void accept(String keyRetrieved, Throwable throwable) { - conds.evaluate { - assert keyRetrieved != null - } - } - } - - when: - RedisFuture redisFuture = asyncCommands.randomkey() - redisFuture.whenCompleteAsync(biConsumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_STATEMENT.key}" "RANDOMKEY" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "hash set and then nest apply to hash getall"() { - setup: - def conds = new AsyncConditions() - - when: - RedisFuture hmsetFuture = asyncCommands.hmset("TESTHM", testHashMap) - hmsetFuture.thenApplyAsync(new Function() { - @Override - Object apply(String setResult) { - conds.evaluate { - assert setResult == "OK" - } - RedisFuture> hmGetAllFuture = asyncCommands.hgetall("TESTHM") - hmGetAllFuture.exceptionally(new Function>() { - @Override - Map apply(Throwable throwable) { - println("unexpected:" + throwable.toString()) - throwable.printStackTrace() - assert false - return null - } - }) - hmGetAllFuture.thenAccept(new Consumer>() { - @Override - void accept(Map hmGetAllResult) { - conds.evaluate { - assert testHashMap == hmGetAllResult - } - } - }) - return null - } - }) - - then: - conds.await() - assertTraces(2) { - trace(0, 1) { - span(0) { - name "HMSET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "HMSET TESTHM firstname ? lastname ? age ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - trace(1, 1) { - span(0) { - name "HGETALL" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "HGETALL TESTHM" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy b/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy deleted file mode 100644 index 15b592c025..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceReactiveClientTest.groovy +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1 - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.lettuce.core.ClientOptions -import io.lettuce.core.RedisClient -import io.lettuce.core.api.StatefulConnection -import io.lettuce.core.api.reactive.RedisReactiveCommands -import io.lettuce.core.api.sync.RedisCommands -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.function.Consumer -import reactor.core.scheduler.Schedulers -import redis.embedded.RedisServer -import spock.lang.Shared -import spock.util.concurrent.AsyncConditions - -class LettuceReactiveClientTest extends AgentTestRunner { - public static final String HOST = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - int port - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - RedisClient redisClient - StatefulConnection connection - RedisReactiveCommands reactiveCommands - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - String dbAddr = HOST + ":" + port + "/" + DB_INDEX - embeddedDbUri = "redis://" + dbAddr - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - println "Using redis: $redisServer.args" - redisServer.start() - redisClient.setOptions(CLIENT_OPTIONS) - - connection = redisClient.connect() - reactiveCommands = connection.reactive() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - - // 1 set - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisClient.shutdown() - redisServer.stop() - } - - def "set command with subscribe on a defined consumer"() { - setup: - def conds = new AsyncConditions() - Consumer consumer = new Consumer() { - @Override - void accept(String res) { - conds.evaluate { - assert res == "OK" - } - } - } - - when: - reactiveCommands.set("TESTSETKEY", "TESTSETVAL").subscribe(consumer) - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "get command with lambda function"() { - setup: - def conds = new AsyncConditions() - - when: - reactiveCommands.get("TESTKEY").subscribe { res -> conds.evaluate { assert res == "TESTVAL" } } - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET TESTKEY" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - // to make sure instrumentation's chained completion stages won't interfere with user's, while still - // recording metrics - def "get non existent key command"() { - setup: - def conds = new AsyncConditions() - final defaultVal = "NOT THIS VALUE" - - when: - reactiveCommands.get("NON_EXISTENT_KEY").defaultIfEmpty(defaultVal).subscribe { - res -> - conds.evaluate { - assert res == defaultVal - } - } - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET NON_EXISTENT_KEY" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - - } - - def "command with no arguments"() { - setup: - def conds = new AsyncConditions() - - when: - reactiveCommands.randomkey().subscribe { - res -> - conds.evaluate { - assert res == "TESTKEY" - } - } - - then: - conds.await() - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_STATEMENT.key}" "RANDOMKEY" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "command flux publisher "() { - setup: - reactiveCommands.command().subscribe() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "COMMAND" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_STATEMENT.key}" "COMMAND" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "non reactive command should not produce span"() { - setup: - String res = null - - when: - res = reactiveCommands.digest() - - then: - res != null - TEST_WRITER.traces.size() == 0 - } - - def "blocking subscriber"() { - when: - runUnderTrace("test-parent") { - reactiveCommands.set("a", "1") - .then(reactiveCommands.get("a")) - .block() - } - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "test-parent" - errored false - attributes { - } - } - span(1) { - name "SET" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET a ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - span(2) { - name "GET" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET a" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "async subscriber"() { - when: - runUnderTrace("test-parent") { - reactiveCommands.set("a", "1") - .then(reactiveCommands.get("a")) - .subscribe() - } - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "test-parent" - errored false - attributes { - } - } - span(1) { - name "SET" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET a ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - span(2) { - name "GET" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET a" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "async subscriber with specific thread pool"() { - when: - runUnderTrace("test-parent") { - reactiveCommands.set("a", "1") - .then(reactiveCommands.get("a")) - .subscribeOn(Schedulers.elastic()) - .subscribe() - } - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - name "test-parent" - errored false - attributes { - } - } - span(1) { - name "SET" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET a ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - span(2) { - name "GET" - kind CLIENT - errored false - childOf span(0) - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET a" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy b/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy deleted file mode 100644 index 197a0bc8da..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientAuthTest.groovy +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1 - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.lettuce.core.ClientOptions -import io.lettuce.core.RedisClient -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import redis.embedded.RedisServer -import spock.lang.Shared - -class LettuceSyncClientAuthTest extends AgentTestRunner { - public static final String HOST = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - int port - @Shared - String password - @Shared - String dbAddr - @Shared - String embeddedDbUri - - @Shared - RedisServer redisServer - - RedisClient redisClient - - def setupSpec() { - port = PortUtils.randomOpenPort() - dbAddr = HOST + ":" + port + "/" + DB_INDEX - embeddedDbUri = "redis://" + dbAddr - password = "password" - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - // Set password - .setting("requirepass " + password) - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - redisClient.setOptions(CLIENT_OPTIONS) - redisServer.start() - } - - def cleanup() { - redisServer.stop() - } - - def "auth command"() { - setup: - def res = redisClient.connect().sync().auth(password) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "AUTH" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "AUTH ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } -} diff --git a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy b/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy deleted file mode 100644 index 68444efe6c..0000000000 --- a/instrumentation/lettuce/lettuce-5.1/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceSyncClientTest.groovy +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce.v5_1 - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static java.nio.charset.StandardCharsets.UTF_8 - -import io.lettuce.core.ClientOptions -import io.lettuce.core.RedisClient -import io.lettuce.core.RedisConnectionException -import io.lettuce.core.ScriptOutputType -import io.lettuce.core.api.StatefulConnection -import io.lettuce.core.api.sync.RedisCommands -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import redis.embedded.RedisServer -import spock.lang.Shared - -class LettuceSyncClientTest extends AgentTestRunner { - public static final String HOST = "127.0.0.1" - public static final int DB_INDEX = 0 - // Disable autoreconnect so we do not get stray traces popping up on server shutdown - public static final ClientOptions CLIENT_OPTIONS = ClientOptions.builder().autoReconnect(false).build() - - @Shared - int port - @Shared - int incorrectPort - @Shared - String dbAddr - @Shared - String dbAddrNonExistent - @Shared - String dbUriNonExistent - @Shared - String embeddedDbUri - @Shared - String embeddedDbLocalhostUri - - @Shared - RedisServer redisServer - - @Shared - Map testHashMap = [ - firstname: "John", - lastname : "Doe", - age : "53" - ] - - RedisClient redisClient - StatefulConnection connection - RedisCommands syncCommands - - def setupSpec() { - port = PortUtils.randomOpenPort() - incorrectPort = PortUtils.randomOpenPort() - dbAddr = HOST + ":" + port + "/" + DB_INDEX - dbAddrNonExistent = HOST + ":" + incorrectPort + "/" + DB_INDEX - dbUriNonExistent = "redis://" + dbAddrNonExistent - embeddedDbUri = "redis://" + dbAddr - embeddedDbLocalhostUri = "redis://localhost:" + port + "/" + DB_INDEX - - redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind " + HOST) - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - } - - def setup() { - redisClient = RedisClient.create(embeddedDbUri) - - redisServer.start() - connection = redisClient.connect() - syncCommands = connection.sync() - - syncCommands.set("TESTKEY", "TESTVAL") - syncCommands.hmset("TESTHM", testHashMap) - - // 2 sets - TEST_WRITER.waitForTraces(2) - TEST_WRITER.clear() - } - - def cleanup() { - connection.close() - redisServer.stop() - } - - def "connect"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - StatefulConnection connection = testConnectionClient.connect() - - then: - // Lettuce tracing does not trace connect - assertTraces(0) {} - - cleanup: - connection.close() - } - - def "connect exception"() { - setup: - RedisClient testConnectionClient = RedisClient.create(dbUriNonExistent) - testConnectionClient.setOptions(CLIENT_OPTIONS) - - when: - testConnectionClient.connect() - - then: - thrown RedisConnectionException - // Lettuce tracing does not trace connect - assertTraces(0) {} - } - - def "set command"() { - setup: - String res = syncCommands.set("TESTSETKEY", "TESTSETVAL") - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "set command localhost"() { - setup: - RedisClient testConnectionClient = RedisClient.create(embeddedDbLocalhostUri) - testConnectionClient.setOptions(CLIENT_OPTIONS) - StatefulConnection connection = testConnectionClient.connect() - String res = connection.sync().set("TESTSETKEY", "TESTSETVAL") - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_NAME.key}" "localhost" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://localhost:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "SET TESTSETKEY ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "get command"() { - setup: - String res = syncCommands.get("TESTKEY") - - expect: - res == "TESTVAL" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET TESTKEY" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "get non existent key command"() { - setup: - String res = syncCommands.get("NON_EXISTENT_KEY") - - expect: - res == null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "GET NON_EXISTENT_KEY" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "command with no arguments"() { - setup: - def keyRetrieved = syncCommands.randomkey() - - expect: - keyRetrieved != null - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RANDOMKEY" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_STATEMENT.key}" "RANDOMKEY" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "list command"() { - setup: - long res = syncCommands.lpush("TESTLIST", "TESTLIST ELEMENT") - - expect: - res == 1 - assertTraces(1) { - trace(0, 1) { - span(0) { - name "LPUSH" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "LPUSH TESTLIST ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "hash set command"() { - setup: - def res = syncCommands.hmset("user", testHashMap) - - expect: - res == "OK" - assertTraces(1) { - trace(0, 1) { - span(0) { - name "HMSET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "HMSET user firstname ? lastname ? age ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "hash getall command"() { - setup: - Map res = syncCommands.hgetall("TESTHM") - - expect: - res == testHashMap - assertTraces(1) { - trace(0, 1) { - span(0) { - name "HGETALL" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "HGETALL TESTHM" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "eval command"() { - given: - def script = "redis.call('lpush', KEYS[1], ARGV[1], ARGV[2]); return redis.call('llen', KEYS[1])" - - when: - def result = syncCommands.eval(script, ScriptOutputType.INTEGER, ["TESTLIST"] as String[], "abc", "def") - - then: - result == 2 - - def b64Script = Base64.encoder.encodeToString(script.getBytes(UTF_8)) - assertTraces(1) { - trace(0, 1) { - span(0) { - name "EVAL" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "EVAL $b64Script 1 TESTLIST ? ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "mset command"() { - when: - def res = syncCommands.mset([ - "key1": "value1", - "key2": "value2" - ]) - - then: - res == "OK" - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "MSET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key}" port - "${SemanticAttributes.DB_CONNECTION_STRING.key}" "redis://127.0.0.1:$port" - "${SemanticAttributes.DB_SYSTEM.key}" "redis" - "${SemanticAttributes.DB_STATEMENT.key}" "MSET key1 ? key2 ?" - } - event(0) { - eventName "redis.encode.start" - } - event(1) { - eventName "redis.encode.end" - } - } - } - } - } - - def "debug segfault command (returns void) with no argument produces no span"() { - setup: - syncCommands.debugSegfault() - - expect: - // lettuce tracing does not trace debug - assertTraces(0) {} - } - - def "shutdown command (returns void) produces no span"() { - setup: - syncCommands.shutdown(false) - - expect: - // lettuce tracing does not trace shutdown - assertTraces(0) {} - } -} diff --git a/instrumentation/lettuce/lettuce-common/lettuce-common.gradle b/instrumentation/lettuce/lettuce-common/lettuce-common.gradle deleted file mode 100644 index 80b3cc1b15..0000000000 --- a/instrumentation/lettuce/lettuce-common/lettuce-common.gradle +++ /dev/null @@ -1 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" diff --git a/instrumentation/lettuce/lettuce-common/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/LettuceArgSplitter.java b/instrumentation/lettuce/lettuce-common/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/LettuceArgSplitter.java deleted file mode 100644 index 68087c078a..0000000000 --- a/instrumentation/lettuce/lettuce-common/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/LettuceArgSplitter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.checkerframework.checker.nullness.qual.Nullable; - -public final class LettuceArgSplitter { - private static final Pattern KEY_PATTERN = - Pattern.compile("((key|value)<(?[^>]+)>|(?[0-9A-Za-z=]+))(\\s+|$)"); - - // this method removes the key|value<...> wrappers around redis keys or values and splits the args - // string - public static List splitArgs(@Nullable String args) { - if (args == null || args.isEmpty()) { - return Collections.emptyList(); - } - - List argsList = new ArrayList<>(); - Matcher m = KEY_PATTERN.matcher(args); - while (m.find()) { - String wrapped = m.group("wrapped"); - if (wrapped != null) { - argsList.add(wrapped); - } else { - argsList.add(m.group("plain")); - } - } - return argsList; - } - - private LettuceArgSplitter() {} -} diff --git a/instrumentation/lettuce/lettuce-common/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/LettuceArgSplitterTest.groovy b/instrumentation/lettuce/lettuce-common/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/LettuceArgSplitterTest.groovy deleted file mode 100644 index 4c3bb91a6e..0000000000 --- a/instrumentation/lettuce/lettuce-common/src/test/groovy/io/opentelemetry/javaagent/instrumentation/lettuce/LettuceArgSplitterTest.groovy +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.lettuce - -import spock.lang.Specification -import spock.lang.Unroll - -class LettuceArgSplitterTest extends Specification { - @Unroll - def "should properly split #desc"() { - expect: - LettuceArgSplitter.splitArgs(args) == result - - where: - desc | args | result - "a null value" | null | [] - "an empty value" | "" | [] - "a single key" | "key" | ["key"] - "a single value" | "value" | ["value"] - "a plain string" | "teststring" | ["teststring"] - "an integer" | "42" | ["42"] - "a base64 value" | "TeST123==" | ["TeST123=="] - "a complex list of args" | "key aSDFgh4321= 5 test value" | ["key", "aSDFgh4321=", "5", "test", "val"] - } -} diff --git a/instrumentation/log4j/log4j-1.2/log4j-1.2.gradle b/instrumentation/log4j/log4j-1.2/log4j-1.2.gradle deleted file mode 100644 index 85c3364955..0000000000 --- a/instrumentation/log4j/log4j-1.2/log4j-1.2.gradle +++ /dev/null @@ -1,25 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "log4j" - module = "log4j" - versions = "[1.2,)" - skipVersions += '1.2.15' //for some reason only this version depends on jms jar which is not found in MavenCentral - } -} - -dependencies { - // 1.2 introduces MDC and there's no version earlier than 1.2.4 available - library group: 'log4j', name: 'log4j', version: '1.2.4' -} - -configurations { - // In order to test the real log4j library we need to remove the log4j transitive - // dependency 'log4j-over-slf4j' brought in by :testing-common which would shadow - // the log4j module under test using a proxy to slf4j instead. - testImplementation.exclude group: 'org.slf4j', module: 'log4j-over-slf4j' - - // See: https://stackoverflow.com/a/9047963/2749853 - testImplementation.exclude group: 'javax.jms', module: 'jms' -} \ No newline at end of file diff --git a/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/CategoryInstrumentation.java b/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/CategoryInstrumentation.java deleted file mode 100644 index b0b084b61f..0000000000 --- a/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/CategoryInstrumentation.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.log4j.v1_2; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.log4j.spi.LoggingEvent; - -public class CategoryInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.log4j.Category"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(named("callAppenders")) - .and(takesArguments(1)) - .and(takesArgument(0, named("org.apache.log4j.spi.LoggingEvent"))), - CategoryInstrumentation.class.getName() + "$CallAppendersAdvice"); - } - - public static class CallAppendersAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter(@Advice.Argument(0) LoggingEvent event) { - InstrumentationContext.get(LoggingEvent.class, Span.class) - .put(event, Java8BytecodeBridge.currentSpan()); - } - } -} diff --git a/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java b/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java deleted file mode 100644 index 5125fdcb08..0000000000 --- a/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.log4j.v1_2; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class Log4j1InstrumentationModule extends InstrumentationModule { - public Log4j1InstrumentationModule() { - super("log4j", "log4j-1.2"); - } - - @Override - public List typeInstrumentations() { - return asList(new CategoryInstrumentation(), new LoggingEventInstrumentation()); - } - - @Override - public Map contextStore() { - return singletonMap("org.apache.log4j.spi.LoggingEvent", Span.class.getName()); - } -} diff --git a/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/LoggingEventInstrumentation.java b/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/LoggingEventInstrumentation.java deleted file mode 100644 index cdf3bd3378..0000000000 --- a/instrumentation/log4j/log4j-1.2/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/LoggingEventInstrumentation.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.log4j.v1_2; - -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.SAMPLED; -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.SPAN_ID; -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.TRACE_ID; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.log4j.MDC; -import org.apache.log4j.spi.LoggingEvent; - -public class LoggingEventInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.log4j.spi.LoggingEvent"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - - transformers.put( - isMethod() - .and(isPublic()) - .and(named("getMDC")) - .and(takesArguments(1)) - .and(takesArgument(0, String.class)), - LoggingEventInstrumentation.class.getName() + "$GetMdcAdvice"); - - transformers.put( - isMethod().and(isPublic()).and(named("getMDCCopy")).and(takesArguments(0)), - LoggingEventInstrumentation.class.getName() + "$GetMdcCopyAdvice"); - - return transformers; - } - - public static class GetMdcAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit( - @Advice.This LoggingEvent event, - @Advice.Argument(0) String key, - @Advice.Return(readOnly = false) Object value) { - if (TRACE_ID.equals(key) || SPAN_ID.equals(key) || SAMPLED.equals(key)) { - if (value != null) { - // Assume already instrumented event if traceId/spanId/sampled is present. - return; - } - - Span span = InstrumentationContext.get(LoggingEvent.class, Span.class).get(event); - if (span == null || !span.getSpanContext().isValid()) { - return; - } - - SpanContext spanContext = span.getSpanContext(); - switch (key) { - case TRACE_ID: - value = spanContext.getTraceIdAsHexString(); - break; - case SPAN_ID: - value = spanContext.getSpanIdAsHexString(); - break; - case SAMPLED: - value = Boolean.toString(spanContext.isSampled()); - break; - default: - // do nothing - } - } - } - } - - public static class GetMdcCopyAdvice { - @SuppressWarnings({"unchecked", "rawtypes"}) - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This LoggingEvent event, - @Advice.FieldValue(value = "mdcCopyLookupRequired", readOnly = false) boolean copyRequired, - @Advice.FieldValue(value = "mdcCopy", readOnly = false) Hashtable mdcCopy) { - // this advice basically replaces the original method - - if (copyRequired) { - copyRequired = false; - - Hashtable mdc = new Hashtable(); - - Hashtable originalMdc = MDC.getContext(); - if (originalMdc != null) { - mdc.putAll(originalMdc); - } - - // Assume already instrumented event if traceId is present. - if (!mdc.contains(TRACE_ID)) { - Span span = InstrumentationContext.get(LoggingEvent.class, Span.class).get(event); - if (span != null && span.getSpanContext().isValid()) { - SpanContext spanContext = span.getSpanContext(); - mdc.put(TRACE_ID, spanContext.getTraceIdAsHexString()); - mdc.put(SPAN_ID, spanContext.getSpanIdAsHexString()); - mdc.put(SAMPLED, Boolean.toString(spanContext.isSampled())); - } - } - - mdcCopy = mdc; - } - } - } -} diff --git a/instrumentation/log4j/log4j-1.2/src/test/groovy/ListAppender.groovy b/instrumentation/log4j/log4j-1.2/src/test/groovy/ListAppender.groovy deleted file mode 100644 index 6960ee0c74..0000000000 --- a/instrumentation/log4j/log4j-1.2/src/test/groovy/ListAppender.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import org.apache.log4j.AppenderSkeleton -import org.apache.log4j.spi.LoggingEvent - -class ListAppender extends AppenderSkeleton { - static events = new ArrayList() - - @Override - protected void append(LoggingEvent loggingEvent) { - events.add(loggingEvent) - } - - @Override - boolean requiresLayout() { - return false - } - - @Override - void close() { - } - - static clearEvents() { - events.clear() - } -} diff --git a/instrumentation/log4j/log4j-1.2/src/test/groovy/Log4j1MdcTest.groovy b/instrumentation/log4j/log4j-1.2/src/test/groovy/Log4j1MdcTest.groovy deleted file mode 100644 index d3664f17fd..0000000000 --- a/instrumentation/log4j/log4j-1.2/src/test/groovy/Log4j1MdcTest.groovy +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.SAMPLED -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.SPAN_ID -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.TRACE_ID - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.TraceUtils -import org.apache.log4j.LogManager - -class Log4j1MdcTest extends AgentTestRunner { - def cleanup() { - ListAppender.clearEvents() - } - - def "no ids when no span"() { - given: - def logger = LogManager.getLogger('TestLogger') - - when: - logger.info("log message 1") - logger.info("log message 2") - - then: - def events = ListAppender.events - - events.size() == 2 - events[0].message == "log message 1" - events[0].getMDC(TRACE_ID) == null - events[0].getMDC(SPAN_ID) == null - events[0].getMDC(SAMPLED) == null - - events[1].message == "log message 2" - events[1].getMDC(TRACE_ID) == null - events[1].getMDC(SPAN_ID) == null - events[1].getMDC(SAMPLED) == null - } - - def "ids when span"() { - given: - def logger = LogManager.getLogger('TestLogger') - - when: - def span1 = TraceUtils.runUnderTrace("test") { - logger.info("log message 1") - Span.current() - } - - logger.info("log message 2") - - def span2 = TraceUtils.runUnderTrace("test 2") { - logger.info("log message 3") - Span.current() - } - - then: - def events = ListAppender.events - - events.size() == 3 - events[0].message == "log message 1" - events[0].getMDC(TRACE_ID) == span1.spanContext.traceIdAsHexString - events[0].getMDC(SPAN_ID) == span1.spanContext.spanIdAsHexString - events[0].getMDC(SAMPLED) == "true" - - events[1].message == "log message 2" - events[1].getMDC(TRACE_ID) == null - events[1].getMDC(SPAN_ID) == null - events[1].getMDC(SAMPLED) == null - - events[2].message == "log message 3" - // this explicit getMDCCopy() call here is to make sure that whole instrumentation is tested - events[2].getMDCCopy() - events[2].getMDC(TRACE_ID) == span2.spanContext.traceIdAsHexString - events[2].getMDC(SPAN_ID) == span2.spanContext.spanIdAsHexString - events[2].getMDC(SAMPLED) == "true" - } -} diff --git a/instrumentation/log4j/log4j-1.2/src/test/resources/log4j.properties b/instrumentation/log4j/log4j-1.2/src/test/resources/log4j.properties deleted file mode 100644 index e7104aab69..0000000000 --- a/instrumentation/log4j/log4j-1.2/src/test/resources/log4j.properties +++ /dev/null @@ -1,2 +0,0 @@ -log4j.rootLogger=INFO, LIST -log4j.appender.LIST=ListAppender diff --git a/instrumentation/log4j/log4j-2.7/log4j-2.7.gradle b/instrumentation/log4j/log4j-2.7/log4j-2.7.gradle deleted file mode 100644 index 71319b3919..0000000000 --- a/instrumentation/log4j/log4j-2.7/log4j-2.7.gradle +++ /dev/null @@ -1,18 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.apache.logging.log4j" - module = "log4j-core" - versions = "[2.7,2.13.2)" - assertInverse = true - } -} - -dependencies { - library group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.7' - - testImplementation project(':instrumentation:log4j:log4j-2-testing') - - latestDepTestLibrary group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.1' -} diff --git a/instrumentation/log4j/log4j-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v2_7/Log4j27InstrumentationModule.java b/instrumentation/log4j/log4j-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v2_7/Log4j27InstrumentationModule.java deleted file mode 100644 index eabfe2a022..0000000000 --- a/instrumentation/log4j/log4j-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v2_7/Log4j27InstrumentationModule.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.log4j.v2_7; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.implementation.bytecode.assign.Assigner.Typing; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.logging.log4j.core.ContextDataInjector; - -@AutoService(InstrumentationModule.class) -public class Log4j27InstrumentationModule extends InstrumentationModule { - public Log4j27InstrumentationModule() { - super("log4j", "log4j-2.7"); - } - - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return hasClassesNamed("org.apache.logging.log4j.core.impl.ContextDataInjectorFactory") - .and(not(hasClassesNamed("org.apache.logging.log4j.core.util.ContextDataProvider"))); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ContextDataInjectorFactoryInstrumentation()); - } - - public static class ContextDataInjectorFactoryInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.apache.logging.log4j.core.impl.ContextDataInjectorFactory"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isMethod() - .and(isPublic()) - .and(isStatic()) - .and(named("createInjector")) - .and(returns(named("org.apache.logging.log4j.core.ContextDataInjector"))), - Log4j27InstrumentationModule.class.getName() + "$CreateInjectorAdvice"); - } - } - - public static class CreateInjectorAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit( - @Advice.Return(typing = Typing.DYNAMIC, readOnly = false) ContextDataInjector injector) { - injector = new SpanDecoratingContextDataInjector(injector); - } - } -} diff --git a/instrumentation/log4j/log4j-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v2_7/SpanDecoratingContextDataInjector.java b/instrumentation/log4j/log4j-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v2_7/SpanDecoratingContextDataInjector.java deleted file mode 100644 index b950f04919..0000000000 --- a/instrumentation/log4j/log4j-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v2_7/SpanDecoratingContextDataInjector.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.log4j.v2_7; - -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.SAMPLED; -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.SPAN_ID; -import static io.opentelemetry.instrumentation.api.log.LoggingContextConstants.TRACE_ID; - -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import java.util.List; -import org.apache.logging.log4j.core.ContextDataInjector; -import org.apache.logging.log4j.core.config.Property; -import org.apache.logging.log4j.util.ReadOnlyStringMap; -import org.apache.logging.log4j.util.SortedArrayStringMap; -import org.apache.logging.log4j.util.StringMap; - -public final class SpanDecoratingContextDataInjector implements ContextDataInjector { - private final ContextDataInjector delegate; - - public SpanDecoratingContextDataInjector(ContextDataInjector delegate) { - this.delegate = delegate; - } - - @Override - public StringMap injectContextData(List list, StringMap stringMap) { - StringMap contextData = delegate.injectContextData(list, stringMap); - - if (contextData.containsKey(TRACE_ID)) { - // Assume already instrumented event if traceId is present. - return contextData; - } - - SpanContext currentContext = Java8BytecodeBridge.currentSpan().getSpanContext(); - if (!currentContext.isValid()) { - return contextData; - } - - StringMap newContextData = new SortedArrayStringMap(contextData); - newContextData.putValue(TRACE_ID, currentContext.getTraceIdAsHexString()); - newContextData.putValue(SPAN_ID, currentContext.getSpanIdAsHexString()); - newContextData.putValue(SAMPLED, Boolean.toString(currentContext.isSampled())); - return newContextData; - } - - @Override - public ReadOnlyStringMap rawContextData() { - return delegate.rawContextData(); - } -} diff --git a/instrumentation/log4j/log4j-2.7/src/test/groovy/Log4j27Test.groovy b/instrumentation/log4j/log4j-2.7/src/test/groovy/Log4j27Test.groovy deleted file mode 100644 index 24e5b98f4c..0000000000 --- a/instrumentation/log4j/log4j-2.7/src/test/groovy/Log4j27Test.groovy +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestTrait - -class Log4j27Test extends Log4j2Test implements AgentTestTrait { -} diff --git a/instrumentation/methods/methods.gradle b/instrumentation/methods/methods.gradle deleted file mode 100644 index 392aee47e8..0000000000 --- a/instrumentation/methods/methods.gradle +++ /dev/null @@ -1,7 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk = true - } -} diff --git a/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodAdvice.java b/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodAdvice.java deleted file mode 100644 index cefaaf5553..0000000000 --- a/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodAdvice.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.methods; - -import static io.opentelemetry.javaagent.instrumentation.methods.MethodTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import net.bytebuddy.asm.Advice; - -public class MethodAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Origin Method method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(method); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } -} diff --git a/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java b/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java deleted file mode 100644 index cc4a39624b..0000000000 --- a/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.methods; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * TraceConfig Instrumentation does not extend Default. - * - *

Instead it directly implements Instrumenter#instrument() and adds one default Instrumenter for - * every configured class+method-list. - * - *

If this becomes a more common use case the building logic should be abstracted out into a - * super class. - */ -@AutoService(InstrumentationModule.class) -public class MethodInstrumentationModule extends InstrumentationModule { - - private static final String TRACE_METHODS_CONFIG = "otel.instrumentation.methods.include"; - - private final List typeInstrumentations; - - public MethodInstrumentationModule() { - super("methods"); - - Map> classMethodsToTrace = - MethodsConfigurationParser.parse(Config.get().getProperty(TRACE_METHODS_CONFIG)); - - typeInstrumentations = - classMethodsToTrace.entrySet().stream() - .filter(e -> !e.getValue().isEmpty()) - .map(e -> new TracerClassInstrumentation(e.getKey(), e.getValue())) - .collect(Collectors.toList()); - } - - @Override - public List typeInstrumentations() { - return typeInstrumentations; - } - - public static class TracerClassInstrumentation implements TypeInstrumentation { - private final String className; - private final Set methodNames; - - public TracerClassInstrumentation(String className, Set methodNames) { - this.className = className; - this.methodNames = methodNames; - } - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed(className); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType(named(className)); - } - - @Override - public Map, String> transformers() { - ElementMatcher.Junction methodMatchers = null; - for (String methodName : methodNames) { - if (methodMatchers == null) { - methodMatchers = named(methodName); - } else { - methodMatchers = methodMatchers.or(named(methodName)); - } - } - - return Collections.singletonMap(methodMatchers, MethodAdvice.class.getName()); - } - } -} diff --git a/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodTracer.java b/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodTracer.java deleted file mode 100644 index 701981c75d..0000000000 --- a/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodTracer.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.methods; - -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; - -public class MethodTracer extends BaseTracer { - private static final MethodTracer TRACER = new MethodTracer(); - - public static MethodTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.external-annotations"; - } -} diff --git a/instrumentation/methods/src/test/groovy/MethodTest.groovy b/instrumentation/methods/src/test/groovy/MethodTest.groovy deleted file mode 100644 index b4a9b16fbc..0000000000 --- a/instrumentation/methods/src/test/groovy/MethodTest.groovy +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import java.util.concurrent.Callable - -class MethodTest extends AgentTestRunner { - static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { - it.setProperty("otel.instrumentation.methods.include", - "package.ClassName[method1,method2];${ConfigTracedCallable.name}[call]") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - static class ConfigTracedCallable implements Callable { - @Override - String call() throws Exception { - return "Hello!" - } - } - - def "test configuration based trace"() { - expect: - new ConfigTracedCallable().call() == "Hello!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ConfigTracedCallable.call" - attributes { - } - } - } - } - } -} diff --git a/instrumentation/mongo/mongo-3.1/mongo-3.1.gradle b/instrumentation/mongo/mongo-3.1/mongo-3.1.gradle deleted file mode 100644 index 9f8d431a9f..0000000000 --- a/instrumentation/mongo/mongo-3.1/mongo-3.1.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.mongodb" - module = "mongo-java-driver" - versions = "[3.1,)" - assertInverse = true - } -} - -dependencies { - implementation(project(':instrumentation:mongo:mongo-common')) - - library group: 'org.mongodb', name: 'mongo-java-driver', version: '3.1.0' - - testImplementation project(':instrumentation:mongo:mongo-testing') - testImplementation group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '1.50.5' -} diff --git a/instrumentation/mongo/mongo-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoClientInstrumentationModule.java b/instrumentation/mongo/mongo-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoClientInstrumentationModule.java deleted file mode 100644 index 9eb5b6d731..0000000000 --- a/instrumentation/mongo/mongo-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoClientInstrumentationModule.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.mongo.v3_1; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import com.mongodb.MongoClientOptions; -import com.mongodb.event.CommandListener; -import io.opentelemetry.javaagent.instrumentation.mongo.TracingCommandListener; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class MongoClientInstrumentationModule extends InstrumentationModule { - - public MongoClientInstrumentationModule() { - super("mongo", "mongo-3.1"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new MongoClientOptionsBuilderInstrumentation()); - } - - private static final class MongoClientOptionsBuilderInstrumentation - implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("com.mongodb.MongoClientOptions$Builder") - .and( - declaresMethod( - named("addCommandListener") - .and( - takesArguments( - new TypeDescription.Latent( - "com.mongodb.event.CommandListener", - Modifier.PUBLIC, - null, - Collections.emptyList()))) - .and(isPublic()))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("build")).and(takesArguments(0)), - MongoClientInstrumentationModule.class.getName() + "$MongoClientAdvice"); - } - } - - public static class MongoClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void injectTraceListener( - @Advice.This MongoClientOptions.Builder builder, - @Advice.FieldValue("commandListeners") List commandListeners) { - for (CommandListener commandListener : commandListeners) { - if (commandListener instanceof TracingCommandListener) { - return; - } - } - builder.addCommandListener(new TracingCommandListener()); - } - } -} diff --git a/instrumentation/mongo/mongo-3.1/src/test/groovy/MongoClientTest.groovy b/instrumentation/mongo/mongo-3.1/src/test/groovy/MongoClientTest.groovy deleted file mode 100644 index d8834b17b5..0000000000 --- a/instrumentation/mongo/mongo-3.1/src/test/groovy/MongoClientTest.groovy +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.mongodb.MongoClient -import com.mongodb.MongoClientOptions -import com.mongodb.MongoTimeoutException -import com.mongodb.ServerAddress -import com.mongodb.client.MongoCollection -import com.mongodb.client.MongoDatabase -import org.bson.BsonDocument -import org.bson.BsonString -import org.bson.Document -import spock.lang.Shared - -class MongoClientTest extends MongoBaseTest { - - @Shared - MongoClient client - - def setup() throws Exception { - client = new MongoClient(new ServerAddress("localhost", port), - MongoClientOptions.builder() - .description("some-description") - .build()) - } - - def cleanup() throws Exception { - client?.close() - client = null - } - - def "test create collection"() { - setup: - MongoDatabase db = client.getDatabase(dbName) - - when: - db.createCollection(collectionName) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName, "{\"create\":\"$collectionName\",\"capped\":\"?\"}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - // Tests the fix for https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/457 - // TracingCommandListener might get added multiple times if clientOptions are built using existing clientOptions or when calling a build method twice. - // This test asserts that duplicate traces are not created in those cases. - def "test create collection with already built ClientOptions"() { - setup: - def clientOptions = client.mongoClientOptions - def newClientOptions = MongoClientOptions.builder(clientOptions).build() - MongoDatabase db = new MongoClient(new ServerAddress("localhost", port), newClientOptions).getDatabase(dbName) - - when: - db.createCollection(collectionName) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName, "{\"create\":\"$collectionName\",\"capped\":\"?\"}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test create collection no description"() { - setup: - MongoDatabase db = new MongoClient("localhost", port).getDatabase(dbName) - - when: - db.createCollection(collectionName) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName, "{\"create\":\"$collectionName\",\"capped\":\"?\"}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test get collection"() { - setup: - MongoDatabase db = client.getDatabase(dbName) - - when: - int count = db.getCollection(collectionName).count() - - then: - count == 0 - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test insert"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - return db.getCollection(collectionName) - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - collection.insertOne(new Document("password", "SECRET")) - - then: - collection.count() == 1 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "insert", collectionName, dbName, "{\"insert\":\"$collectionName\",\"ordered\":\"?\",\"documents\":[{\"_id\":\"?\",\"password\":\"?\"}]}") - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test update"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - def coll = db.getCollection(collectionName) - coll.insertOne(new Document("password", "OLDPW")) - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def result = collection.updateOne( - new BsonDocument("password", new BsonString("OLDPW")), - new BsonDocument('$set', new BsonDocument("password", new BsonString("NEWPW")))) - - then: - result.modifiedCount == 1 - collection.count() == 1 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "update", collectionName, dbName, "{\"update\":\"$collectionName\",\"ordered\":\"?\",\"updates\":[{\"q\":{\"password\":\"?\"},\"u\":{\"\$set\":{\"password\":\"?\"}}}]}") - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test delete"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - def coll = db.getCollection(collectionName) - coll.insertOne(new Document("password", "SECRET")) - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def result = collection.deleteOne(new BsonDocument("password", new BsonString("SECRET"))) - - then: - result.deletedCount == 1 - collection.count() == 0 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "delete", collectionName, dbName, "{\"delete\":\"$collectionName\",\"ordered\":\"?\",\"deletes\":[{\"q\":{\"password\":\"?\"},\"limit\":\"?\"}]}") - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test collection name for getMore command"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - def coll = db.getCollection(collectionName) - coll.insertMany([new Document("_id", 0), new Document("_id", 1), new Document("_id", 2)]) - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - collection.find().filter(new Document("_id", new Document('$gte', 0))) - .batchSize(2).into(new ArrayList()) - - then: - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "find", collectionName, dbName, '{"find":"testCollection","filter":{"_id":{"$gte":"?"}},"batchSize":"?"}') - } - trace(1, 1) { - mongoSpan(it, 0, "getMore", collectionName, dbName, '{"getMore":"?","collection":"?","batchSize":"?"}') - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test error"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - return db.getCollection(collectionName) - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - collection.updateOne(new BsonDocument(), new BsonDocument()) - - then: - thrown(IllegalArgumentException) - // Unfortunately not caught by our instrumentation. - assertTraces(0) {} - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test client failure"() { - setup: - def options = MongoClientOptions.builder().serverSelectionTimeout(10).build() - def client = new MongoClient(new ServerAddress("localhost", UNUSABLE_PORT), [], options) - - when: - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - - then: - thrown(MongoTimeoutException) - // Unfortunately not caught by our instrumentation. - assertTraces(0) {} - - where: - dbName = "test_db" - collectionName = "testCollection" - } -} diff --git a/instrumentation/mongo/mongo-3.1/src/test/groovy/MongoClientTracerTest.groovy b/instrumentation/mongo/mongo-3.1/src/test/groovy/MongoClientTracerTest.groovy deleted file mode 100644 index b0468b40c2..0000000000 --- a/instrumentation/mongo/mongo-3.1/src/test/groovy/MongoClientTracerTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static java.util.Arrays.asList - -import io.opentelemetry.javaagent.instrumentation.mongo.MongoClientTracer -import org.bson.BsonArray -import org.bson.BsonDocument -import org.bson.BsonInt32 -import org.bson.BsonString -import spock.lang.Specification - -class MongoClientTracerTest extends Specification { - def 'should normalize queries to json'() { - setup: - def tracer = new MongoClientTracer() - - expect: - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonInt32(1))) == - '{"cmd": "?"}' - - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonInt32(1)) - .append("sub", new BsonDocument("a", new BsonInt32(1)))) == - '{"cmd": "?", "sub": {"a": "?"}}' - - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonInt32(1)) - .append("sub", new BsonArray(asList(new BsonInt32(1))))) == - '{"cmd": "?", "sub": ["?"]}' - } - - def 'should only preserve string value if it is the value of the first top-level key'() { - setup: - def tracer = new MongoClientTracer() - - expect: - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonString("c")) - .append("f", new BsonString("c")) - .append("sub", new BsonString("c"))) == - '{"cmd": "c", "f": "?", "sub": "?"}' - } - - def 'should truncate simple command'() { - setup: - def tracer = new MongoClientTracer(20) - - def normalized = normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonString("c")) - .append("f1", new BsonString("c1")) - .append("f2", new BsonString("c2"))) - expect: - // this can vary because of different whitespace for different mongo versions - normalized == '{"cmd": "c", "f1": "' || normalized == '{"cmd": "c", "f1" ' - } - - def 'should truncate array'() { - setup: - def tracer = new MongoClientTracer(27) - - def normalized = normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonString("c")) - .append("f1", new BsonArray(Arrays.asList(new BsonString("c1"), new BsonString("c2")))) - .append("f2", new BsonString("c3"))) - expect: - // this can vary because of different whitespace for different mongo versions - normalized == '{"cmd": "c", "f1": ["?", "?' || normalized == '{"cmd": "c", "f1": ["?",' - } - - def normalizeQueryAcrossVersions(MongoClientTracer tracer, BsonDocument query) { - return normalizeAcrossVersions(tracer.normalizeQuery(query)) - } - - def normalizeAcrossVersions(String json) { - json = json.replaceAll('\\{ ', '{') - json = json.replaceAll(' }', '}') - json = json.replaceAll(' :', ':') - return json - } -} diff --git a/instrumentation/mongo/mongo-3.7/mongo-3.7.gradle b/instrumentation/mongo/mongo-3.7/mongo-3.7.gradle deleted file mode 100644 index 770b1f1b5d..0000000000 --- a/instrumentation/mongo/mongo-3.7/mongo-3.7.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.mongodb" - module = "mongo-java-driver" - versions = "[3.7,)" - assertInverse = true - } -} - -dependencies { - implementation(project(':instrumentation:mongo:mongo-common')) - - // a couple of test attribute verifications don't pass until 3.8.0 - library group: 'org.mongodb', name: 'mongo-java-driver', version: '3.8.0' - - testImplementation project(':instrumentation:mongo:mongo-testing') - testImplementation group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '1.50.5' -} diff --git a/instrumentation/mongo/mongo-3.7/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoClientInstrumentationModule.java b/instrumentation/mongo/mongo-3.7/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoClientInstrumentationModule.java deleted file mode 100644 index 656a523a77..0000000000 --- a/instrumentation/mongo/mongo-3.7/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoClientInstrumentationModule.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.mongo.v3_7; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import com.mongodb.MongoClientSettings; -import com.mongodb.event.CommandListener; -import io.opentelemetry.javaagent.instrumentation.mongo.TracingCommandListener; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class MongoClientInstrumentationModule extends InstrumentationModule { - - public MongoClientInstrumentationModule() { - super("mongo", "mongo-3.7"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new MongoClientSettingsBuilderInstrumentation()); - } - - private static final class MongoClientSettingsBuilderInstrumentation - implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("com.mongodb.MongoClientSettings$Builder") - .and( - declaresMethod( - named("addCommandListener") - .and( - takesArguments( - new TypeDescription.Latent( - "com.mongodb.event.CommandListener", - Modifier.PUBLIC, - null, - Collections.emptyList()))) - .and(isPublic()))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("build")).and(takesArguments(0)), - MongoClientInstrumentationModule.class.getName() + "$MongoClientAdvice"); - } - } - - public static class MongoClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void injectTraceListener( - @Advice.This MongoClientSettings.Builder builder, - @Advice.FieldValue("commandListeners") List commandListeners) { - for (CommandListener commandListener : commandListeners) { - if (commandListener instanceof TracingCommandListener) { - return; - } - } - builder.addCommandListener(new TracingCommandListener()); - } - } -} diff --git a/instrumentation/mongo/mongo-3.7/src/test/groovy/MongoClientTest.groovy b/instrumentation/mongo/mongo-3.7/src/test/groovy/MongoClientTest.groovy deleted file mode 100644 index d80ddb5339..0000000000 --- a/instrumentation/mongo/mongo-3.7/src/test/groovy/MongoClientTest.groovy +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.mongodb.MongoClientSettings -import com.mongodb.MongoTimeoutException -import com.mongodb.ServerAddress -import com.mongodb.client.MongoClient -import com.mongodb.client.MongoClients -import com.mongodb.client.MongoCollection -import com.mongodb.client.MongoDatabase -import org.bson.BsonDocument -import org.bson.BsonString -import org.bson.Document -import spock.lang.Shared - -class MongoClientTest extends MongoBaseTest { - - @Shared - MongoClient client - - def setup() throws Exception { - client = MongoClients.create(MongoClientSettings.builder() - .applyToClusterSettings({ builder -> - builder.hosts(Arrays.asList( - new ServerAddress("localhost", port))) - .description("some-description") - }) - .build()) - } - - def cleanup() throws Exception { - client?.close() - client = null - } - - def "test create collection"() { - setup: - MongoDatabase db = client.getDatabase(dbName) - - when: - db.createCollection(collectionName) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName, "{\"create\":\"$collectionName\",\"capped\":\"?\"}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - // Tests the fix for https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/457 - // TracingCommandListener might get added multiple times if ClientSettings are built using existing ClientSettings or when calling a build method twice. - // This test asserts that duplicate traces are not created in those cases. - def "test create collection with already built ClientSettings"() { - setup: - def clientSettings = MongoClientSettings.builder() - .applyToClusterSettings({ builder -> - builder.hosts(Arrays.asList( - new ServerAddress("localhost", port))) - .description("some-description") - }) - .build() - def newClientSettings = MongoClientSettings.builder(clientSettings).build() - MongoDatabase db = MongoClients.create(newClientSettings).getDatabase(dbName) - - when: - db.createCollection(collectionName) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName, "{\"create\":\"$collectionName\",\"capped\":\"?\"}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test create collection no description"() { - setup: - MongoDatabase db = MongoClients.create("mongodb://localhost:" + port).getDatabase(dbName) - - when: - db.createCollection(collectionName) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName, "{\"create\":\"$collectionName\",\"capped\":\"?\"}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test get collection"() { - setup: - MongoDatabase db = client.getDatabase(dbName) - - when: - int count = db.getCollection(collectionName).count() - - then: - count == 0 - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test insert"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - return db.getCollection(collectionName) - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - collection.insertOne(new Document("password", "SECRET")) - - then: - collection.count() == 1 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "insert", collectionName, dbName, "{\"insert\":\"$collectionName\",\"ordered\":\"?\",\"documents\":[{\"_id\":\"?\",\"password\":\"?\"}]}") - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test update"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - def coll = db.getCollection(collectionName) - coll.insertOne(new Document("password", "OLDPW")) - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def result = collection.updateOne( - new BsonDocument("password", new BsonString("OLDPW")), - new BsonDocument('$set', new BsonDocument("password", new BsonString("NEWPW")))) - - then: - result.modifiedCount == 1 - collection.count() == 1 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "update", collectionName, dbName, "{\"update\":\"$collectionName\",\"ordered\":\"?\",\"updates\":[{\"q\":{\"password\":\"?\"},\"u\":{\"\$set\":{\"password\":\"?\"}}}]}") - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test delete"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - def coll = db.getCollection(collectionName) - coll.insertOne(new Document("password", "SECRET")) - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def result = collection.deleteOne(new BsonDocument("password", new BsonString("SECRET"))) - - then: - result.deletedCount == 1 - collection.count() == 0 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "delete", collectionName, dbName, "{\"delete\":\"$collectionName\",\"ordered\":\"?\",\"deletes\":[{\"q\":{\"password\":\"?\"},\"limit\":\"?\"}]}") - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName, "{\"count\":\"$collectionName\",\"query\":{}}") - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test collection name for getMore command"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - def coll = db.getCollection(collectionName) - coll.insertMany([new Document("_id", 0), new Document("_id", 1), new Document("_id", 2)]) - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - collection.find().filter(new Document("_id", new Document('$gte', 0))) - .batchSize(2).into(new ArrayList()) - - then: - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "find", collectionName, dbName, '{"find":"testCollection","filter":{"_id":{"$gte":"?"}},"batchSize":"?"}') - } - trace(1, 1) { - mongoSpan(it, 0, "getMore", collectionName, dbName, '{"getMore":"?","collection":"?","batchSize":"?"}') - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test error"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - return db.getCollection(collectionName) - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - collection.updateOne(new BsonDocument(), new BsonDocument()) - - then: - thrown(IllegalArgumentException) - // Unfortunately not caught by our instrumentation. - assertTraces(0) {} - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test client failure"() { - setup: - def client = MongoClients.create("mongodb://localhost:" + UNUSABLE_PORT + "/?connectTimeoutMS=10") - - when: - MongoDatabase db = client.getDatabase(dbName) - db.createCollection(collectionName) - - then: - thrown(MongoTimeoutException) - // Unfortunately not caught by our instrumentation. - assertTraces(0) {} - - where: - dbName = "test_db" - collectionName = "testCollection" - } -} diff --git a/instrumentation/mongo/mongo-3.7/src/test/groovy/MongoClientTracerTest.groovy b/instrumentation/mongo/mongo-3.7/src/test/groovy/MongoClientTracerTest.groovy deleted file mode 100644 index b0468b40c2..0000000000 --- a/instrumentation/mongo/mongo-3.7/src/test/groovy/MongoClientTracerTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static java.util.Arrays.asList - -import io.opentelemetry.javaagent.instrumentation.mongo.MongoClientTracer -import org.bson.BsonArray -import org.bson.BsonDocument -import org.bson.BsonInt32 -import org.bson.BsonString -import spock.lang.Specification - -class MongoClientTracerTest extends Specification { - def 'should normalize queries to json'() { - setup: - def tracer = new MongoClientTracer() - - expect: - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonInt32(1))) == - '{"cmd": "?"}' - - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonInt32(1)) - .append("sub", new BsonDocument("a", new BsonInt32(1)))) == - '{"cmd": "?", "sub": {"a": "?"}}' - - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonInt32(1)) - .append("sub", new BsonArray(asList(new BsonInt32(1))))) == - '{"cmd": "?", "sub": ["?"]}' - } - - def 'should only preserve string value if it is the value of the first top-level key'() { - setup: - def tracer = new MongoClientTracer() - - expect: - normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonString("c")) - .append("f", new BsonString("c")) - .append("sub", new BsonString("c"))) == - '{"cmd": "c", "f": "?", "sub": "?"}' - } - - def 'should truncate simple command'() { - setup: - def tracer = new MongoClientTracer(20) - - def normalized = normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonString("c")) - .append("f1", new BsonString("c1")) - .append("f2", new BsonString("c2"))) - expect: - // this can vary because of different whitespace for different mongo versions - normalized == '{"cmd": "c", "f1": "' || normalized == '{"cmd": "c", "f1" ' - } - - def 'should truncate array'() { - setup: - def tracer = new MongoClientTracer(27) - - def normalized = normalizeQueryAcrossVersions(tracer, - new BsonDocument("cmd", new BsonString("c")) - .append("f1", new BsonArray(Arrays.asList(new BsonString("c1"), new BsonString("c2")))) - .append("f2", new BsonString("c3"))) - expect: - // this can vary because of different whitespace for different mongo versions - normalized == '{"cmd": "c", "f1": ["?", "?' || normalized == '{"cmd": "c", "f1": ["?",' - } - - def normalizeQueryAcrossVersions(MongoClientTracer tracer, BsonDocument query) { - return normalizeAcrossVersions(tracer.normalizeQuery(query)) - } - - def normalizeAcrossVersions(String json) { - json = json.replaceAll('\\{ ', '{') - json = json.replaceAll(' }', '}') - json = json.replaceAll(' :', ':') - return json - } -} diff --git a/instrumentation/mongo/mongo-async-3.3/javaagent/src/test/groovy/MongoAsyncClientTest.groovy b/instrumentation/mongo/mongo-async-3.3/javaagent/src/test/groovy/MongoAsyncClientTest.groovy index f9e705b0cc..3c67e56e29 100644 --- a/instrumentation/mongo/mongo-async-3.3/javaagent/src/test/groovy/MongoAsyncClientTest.groovy +++ b/instrumentation/mongo/mongo-async-3.3/javaagent/src/test/groovy/MongoAsyncClientTest.groovy @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import com.mongodb.ConnectionString import com.mongodb.async.SingleResultCallback @@ -16,9 +16,9 @@ import com.mongodb.async.client.MongoDatabase import com.mongodb.client.result.DeleteResult import com.mongodb.client.result.UpdateResult import com.mongodb.connection.ClusterSettings +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.sdk.trace.data.SpanData -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.concurrent.CompletableFuture import java.util.concurrent.CountDownLatch import org.bson.BsonDocument diff --git a/instrumentation/mongo/mongo-async-3.3/mongo-async-3.3.gradle b/instrumentation/mongo/mongo-async-3.3/mongo-async-3.3.gradle deleted file mode 100644 index e7ec372523..0000000000 --- a/instrumentation/mongo/mongo-async-3.3/mongo-async-3.3.gradle +++ /dev/null @@ -1,22 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.mongodb" - module = "mongodb-driver-async" - versions = "[3.3,)" - extraDependency 'org.mongodb:mongo-java-driver:3.3.0' - assertInverse = true - } -} - -dependencies { - implementation(project(':instrumentation:mongo:mongo-common')) - - library group: 'org.mongodb', name: 'mongodb-driver-async', version: '3.3.0' - - testImplementation project(':instrumentation:mongo:mongo-testing') - testImplementation group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '1.50.5' - - testImplementation project(':instrumentation:mongo:mongo-3.7') -} diff --git a/instrumentation/mongo/mongo-async-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoAsyncClientInstrumentationModule.java b/instrumentation/mongo/mongo-async-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoAsyncClientInstrumentationModule.java deleted file mode 100644 index 1e38cfea2b..0000000000 --- a/instrumentation/mongo/mongo-async-3.3/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoAsyncClientInstrumentationModule.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.mongoasync.v3_3; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresField; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import com.mongodb.async.client.MongoClientSettings; -import com.mongodb.event.CommandListener; -import io.opentelemetry.javaagent.instrumentation.mongo.TracingCommandListener; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class MongoAsyncClientInstrumentationModule extends InstrumentationModule { - - public MongoAsyncClientInstrumentationModule() { - super("mongo-async", "mongo-async-3.3", "mongo"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new MongoClientSettingsBuildersInstrumentation()); - } - - private static final class MongoClientSettingsBuildersInstrumentation - implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("com.mongodb.async.client.MongoClientSettings$Builder") - .and( - declaresMethod( - named("addCommandListener") - .and( - takesArguments( - new TypeDescription.Latent( - "com.mongodb.event.CommandListener", - Modifier.PUBLIC, - null, - Collections.emptyList()))) - .and(isPublic()))) - .and(declaresField(named("commandListeners"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(named("build")).and(takesArguments(0)), - MongoAsyncClientInstrumentationModule.class.getName() + "$MongoAsyncClientAdvice"); - } - } - - public static class MongoAsyncClientAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void injectTraceListener( - @Advice.This MongoClientSettings.Builder builder, - @Advice.FieldValue("commandListeners") List commandListeners) { - for (CommandListener commandListener : commandListeners) { - if (commandListener instanceof TracingCommandListener) { - return; - } - } - builder.addCommandListener(new TracingCommandListener()); - } - } -} diff --git a/instrumentation/mongo/mongo-async-3.3/src/test/groovy/MongoAsyncClientTest.groovy b/instrumentation/mongo/mongo-async-3.3/src/test/groovy/MongoAsyncClientTest.groovy deleted file mode 100644 index 3c67e56e29..0000000000 --- a/instrumentation/mongo/mongo-async-3.3/src/test/groovy/MongoAsyncClientTest.groovy +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.mongodb.ConnectionString -import com.mongodb.async.SingleResultCallback -import com.mongodb.async.client.MongoClient -import com.mongodb.async.client.MongoClientSettings -import com.mongodb.async.client.MongoClients -import com.mongodb.async.client.MongoCollection -import com.mongodb.async.client.MongoDatabase -import com.mongodb.client.result.DeleteResult -import com.mongodb.client.result.UpdateResult -import com.mongodb.connection.ClusterSettings -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.concurrent.CompletableFuture -import java.util.concurrent.CountDownLatch -import org.bson.BsonDocument -import org.bson.BsonString -import org.bson.Document -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(10) -class MongoAsyncClientTest extends MongoBaseTest { - - @Shared - MongoClient client - - def setup() throws Exception { - client = MongoClients.create( - MongoClientSettings.builder() - .clusterSettings( - ClusterSettings.builder() - .description("some-description") - .applyConnectionString(new ConnectionString("mongodb://localhost:$port")) - .build()) - .build()) - } - - def cleanup() throws Exception { - client?.close() - client = null - } - - def "test create collection"() { - setup: - MongoDatabase db = client.getDatabase(dbName) - - when: - db.createCollection(collectionName, toCallback {}) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"create\":\"$collectionName\",\"capped\":\"?\"}" || - it == "{\"create\": \"$collectionName\", \"capped\": \"?\", \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - // Tests the fix for https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/457 - // TracingCommandListener might get added multiple times if ClientSettings are built using existing ClientSettings or when calling a build method twice. - // This test asserts that duplicate traces are not created in those cases. - def "test create collection with already built ClientSettings"() { - setup: - def clientSettings = client.settings - def newClientSettings = MongoClientSettings.builder(clientSettings).build() - MongoDatabase db = MongoClients.create(newClientSettings).getDatabase(dbName) - - when: - db.createCollection(collectionName, toCallback {}) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"create\":\"$collectionName\",\"capped\":\"?\"}" || - it == "{\"create\": \"$collectionName\", \"capped\": \"?\", \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test create collection no description"() { - setup: - MongoDatabase db = MongoClients.create("mongodb://localhost:$port").getDatabase(dbName) - - when: - db.createCollection(collectionName, toCallback {}) - - then: - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "create", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"create\":\"$collectionName\",\"capped\":\"?\"}" || - it == "{\"create\": \"$collectionName\", \"capped\": \"?\", \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test get collection"() { - setup: - MongoDatabase db = client.getDatabase(dbName) - - when: - def count = new CompletableFuture() - db.getCollection(collectionName).count toCallback { count.complete(it) } - - then: - count.get() == 0 - assertTraces(1) { - trace(0, 1) { - mongoSpan(it, 0, "count", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"count\":\"$collectionName\",\"query\":{}}" || - it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test insert"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - def latch1 = new CountDownLatch(1) - db.createCollection(collectionName, toCallback { latch1.countDown() }) - latch1.await() - return db.getCollection(collectionName) - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def count = new CompletableFuture() - collection.insertOne(new Document("password", "SECRET"), toCallback { - collection.count toCallback { count.complete(it) } - }) - - then: - count.get() == 1 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "insert", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"insert\":\"$collectionName\",\"ordered\":\"?\",\"documents\":[{\"_id\":\"?\",\"password\":\"?\"}]}" || - it == "{\"insert\": \"$collectionName\", \"ordered\": \"?\", \"\$db\": \"?\", \"documents\": [{\"_id\": \"?\", \"password\": \"?\"}]}" - true - } - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"count\":\"$collectionName\",\"query\":{}}" || - it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test update"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - def latch1 = new CountDownLatch(1) - db.createCollection(collectionName, toCallback { latch1.countDown() }) - latch1.await() - def coll = db.getCollection(collectionName) - def latch2 = new CountDownLatch(1) - coll.insertOne(new Document("password", "OLDPW"), toCallback { latch2.countDown() }) - latch2.await() - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def result = new CompletableFuture() - def count = new CompletableFuture() - collection.updateOne( - new BsonDocument("password", new BsonString("OLDPW")), - new BsonDocument('$set', new BsonDocument("password", new BsonString("NEWPW"))), toCallback { - result.complete(it) - collection.count toCallback { count.complete(it) } - }) - - then: - result.get().modifiedCount == 1 - count.get() == 1 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "update", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"update\":\"$collectionName\",\"ordered\":\"?\",\"updates\":[{\"q\":{\"password\":\"?\"},\"u\":{\"\$set\":{\"password\":\"?\"}}}]}" || - it == "{\"update\": \"?\", \"ordered\": \"?\", \"\$db\": \"?\", \"updates\": [{\"q\": {\"password\": \"?\"}, \"u\": {\"\$set\": {\"password\": \"?\"}}}]}" - true - } - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"count\":\"$collectionName\",\"query\":{}}" || - it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - def "test delete"() { - setup: - MongoCollection collection = runUnderTrace("setup") { - MongoDatabase db = client.getDatabase(dbName) - def latch1 = new CountDownLatch(1) - db.createCollection(collectionName, toCallback { latch1.countDown() }) - latch1.await() - def coll = db.getCollection(collectionName) - def latch2 = new CountDownLatch(1) - coll.insertOne(new Document("password", "SECRET"), toCallback { latch2.countDown() }) - latch2.await() - return coll - } - TEST_WRITER.waitForTraces(1) - TEST_WRITER.clear() - - when: - def result = new CompletableFuture() - def count = new CompletableFuture() - collection.deleteOne(new BsonDocument("password", new BsonString("SECRET")), toCallback { - result.complete(it) - collection.count toCallback { count.complete(it) } - }) - - then: - result.get().deletedCount == 1 - count.get() == 0 - assertTraces(2) { - trace(0, 1) { - mongoSpan(it, 0, "delete", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"delete\":\"$collectionName\",\"ordered\":\"?\",\"deletes\":[{\"q\":{\"password\":\"?\"},\"limit\":\"?\"}]}" || - it == "{\"delete\": \"?\", \"ordered\": \"?\", \"\$db\": \"?\", \"deletes\": [{\"q\": {\"password\": \"?\"}, \"limit\": \"?\"}]}" - true - } - } - trace(1, 1) { - mongoSpan(it, 0, "count", collectionName, dbName) { - assert it.replaceAll(" ", "") == "{\"count\":\"$collectionName\",\"query\":{}}" || - it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}" - true - } - } - } - - where: - dbName = "test_db" - collectionName = "testCollection" - } - - SingleResultCallback toCallback(Closure closure) { - return new SingleResultCallback() { - @Override - void onResult(Object result, Throwable t) { - if (t) { - closure.call(t) - } else { - closure.call(result) - } - } - } - } - - def mongoSpan(TraceAssert trace, int index, - String operation, String collection, - String dbName, Closure statementEval, - Object parentSpan = null, Throwable exception = null) { - trace.span(index) { - name statementEval - kind CLIENT - if (parentSpan == null) { - hasNoParent() - } else { - childOf((SpanData) parentSpan) - } - attributes { - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_CONNECTION_STRING.key" "mongodb://localhost:" + port - "$SemanticAttributes.DB_STATEMENT.key" statementEval - "$SemanticAttributes.DB_SYSTEM.key" "mongodb" - "$SemanticAttributes.DB_NAME.key" dbName - "$SemanticAttributes.DB_OPERATION.key" operation - "$SemanticAttributes.DB_MONGODB_COLLECTION.key" collection - } - } - } -} diff --git a/instrumentation/mongo/mongo-common/mongo-common.gradle b/instrumentation/mongo/mongo-common/mongo-common.gradle deleted file mode 100644 index 634e2995d0..0000000000 --- a/instrumentation/mongo/mongo-common/mongo-common.gradle +++ /dev/null @@ -1,5 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - compileOnly group: 'org.mongodb', name: 'mongo-java-driver', version: '3.1.0' -} diff --git a/instrumentation/mongo/mongo-common/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java b/instrumentation/mongo/mongo-common/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java deleted file mode 100644 index 1043e76bbc..0000000000 --- a/instrumentation/mongo/mongo-common/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/MongoClientTracer.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.mongo; - -import static java.util.Arrays.asList; - -import com.mongodb.ServerAddress; -import com.mongodb.connection.ConnectionDescription; -import com.mongodb.event.CommandStartedEvent; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import org.bson.BsonArray; -import org.bson.BsonDocument; -import org.bson.BsonValue; -import org.bson.json.JsonWriter; -import org.bson.json.JsonWriterSettings; - -public class MongoClientTracer extends DatabaseClientTracer { - private static final MongoClientTracer TRACER = new MongoClientTracer(); - - private final int maxNormalizedQueryLength; - private final JsonWriterSettings jsonWriterSettings; - - public MongoClientTracer() { - this(32 * 1024); - } - - public MongoClientTracer(int maxNormalizedQueryLength) { - this.maxNormalizedQueryLength = maxNormalizedQueryLength; - this.jsonWriterSettings = createJsonWriterSettings(maxNormalizedQueryLength); - } - - public static MongoClientTracer tracer() { - return TRACER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.mongo"; - } - - @Override - protected String dbSystem(CommandStartedEvent event) { - return DbSystem.MONGODB; - } - - @Override - protected Span onConnection(Span span, CommandStartedEvent event) { - span.setAttribute(SemanticAttributes.DB_OPERATION, event.getCommandName()); - String collection = collectionName(event); - if (collection != null) { - span.setAttribute(SemanticAttributes.DB_MONGODB_COLLECTION, collection); - } - return super.onConnection(span, event); - } - - @Override - protected String dbName(CommandStartedEvent event) { - return event.getDatabaseName(); - } - - @Override - protected InetSocketAddress peerAddress(CommandStartedEvent event) { - if (event.getConnectionDescription() != null - && event.getConnectionDescription().getServerAddress() != null) { - return event.getConnectionDescription().getServerAddress().getSocketAddress(); - } else { - return null; - } - } - - @Override - protected String dbConnectionString(CommandStartedEvent event) { - ConnectionDescription connectionDescription = event.getConnectionDescription(); - if (connectionDescription != null) { - ServerAddress sa = connectionDescription.getServerAddress(); - if (sa != null) { - // https://docs.mongodb.com/manual/reference/connection-string/ - String host = sa.getHost(); - int port = sa.getPort(); - if (host != null && port != 0) { - return "mongodb://" + host + ":" + port; - } - } - } - return null; - } - - private static final Method IS_TRUNCATED_METHOD; - - static { - IS_TRUNCATED_METHOD = - Arrays.stream(JsonWriter.class.getMethods()) - .filter(method -> method.getName().equals("isTruncated")) - .findFirst() - .orElse(null); - } - - /** - * The values of these mongo fields will not be scrubbed out. This allows the non-sensitive - * collection names to be captured. - */ - private static final List UNSCRUBBED_FIELDS = - asList("ordered", "insert", "count", "find", "create"); - - private JsonWriterSettings createJsonWriterSettings(int maxNormalizedQueryLength) { - JsonWriterSettings settings = new JsonWriterSettings(false); - try { - // The static JsonWriterSettings.builder() method was introduced in the 3.5 release - Optional buildMethod = - Arrays.stream(JsonWriterSettings.class.getMethods()) - .filter(method -> method.getName().equals("builder")) - .findFirst(); - if (buildMethod.isPresent()) { - Class builderClass = buildMethod.get().getReturnType(); - Object builder = buildMethod.get().invoke(null, (Object[]) null); - - // The JsonWriterSettings.Builder.indent method was introduced in the 3.5 release, - // but checking anyway - Optional indentMethod = - Arrays.stream(builderClass.getMethods()) - .filter(method -> method.getName().equals("indent")) - .findFirst(); - if (indentMethod.isPresent()) { - indentMethod.get().invoke(builder, false); - } - - // The JsonWriterSettings.Builder.maxLength method was introduced in the 3.7 release - Optional maxLengthMethod = - Arrays.stream(builderClass.getMethods()) - .filter(method -> method.getName().equals("maxLength")) - .findFirst(); - if (maxLengthMethod.isPresent()) { - maxLengthMethod.get().invoke(builder, maxNormalizedQueryLength); - } - settings = - (JsonWriterSettings) - builderClass.getMethod("build", (Class[]) null).invoke(builder, (Object[]) null); - } - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ignored) { - } - return settings; - } - - @Override - public String normalizeQuery(BsonDocument command) { - StringWriter stringWriter = new StringWriter(128); - writeScrubbed(command, new JsonWriter(stringWriter, jsonWriterSettings), true); - // If using MongoDB driver >= 3.7, the substring invocation will be a no-op due to use of - // JsonWriterSettings.Builder.maxLength in the static initializer for JSON_WRITER_SETTINGS - return stringWriter - .getBuffer() - .substring(0, Math.min(maxNormalizedQueryLength, stringWriter.getBuffer().length())); - } - - private static final String HIDDEN_CHAR = "?"; - - private static boolean writeScrubbed(BsonDocument origin, JsonWriter writer, boolean isRoot) { - writer.writeStartDocument(); - boolean firstField = true; - for (Map.Entry entry : origin.entrySet()) { - writer.writeName(entry.getKey()); - // the first field of the root document is the command name, so we preserve its value - // (which for most CRUD commands is the collection name) - if (isRoot && firstField && entry.getValue().isString()) { - writer.writeString(entry.getValue().asString().getValue()); - } else { - if (writeScrubbed(entry.getValue(), writer)) { - return true; - } - } - firstField = false; - } - writer.writeEndDocument(); - return false; - } - - private static boolean writeScrubbed(BsonArray origin, JsonWriter writer) { - writer.writeStartArray(); - for (BsonValue value : origin) { - if (writeScrubbed(value, writer)) { - return true; - } - } - writer.writeEndArray(); - return false; - } - - private static boolean writeScrubbed(BsonValue origin, JsonWriter writer) { - if (origin.isDocument()) { - return writeScrubbed(origin.asDocument(), writer, false); - } else if (origin.isArray()) { - return writeScrubbed(origin.asArray(), writer); - } else { - writer.writeString(HIDDEN_CHAR); - return isTruncated(writer); - } - } - - private static boolean isTruncated(JsonWriter writer) { - if (IS_TRUNCATED_METHOD == null) { - return false; - } else { - try { - return (boolean) IS_TRUNCATED_METHOD.invoke(writer, (Object[]) null); - } catch (IllegalAccessException | InvocationTargetException ignored) { - return false; - } - } - } - - private static final Set COMMANDS_WITH_COLLECTION_NAME_AS_VALUE = - new HashSet<>( - asList( - "aggregate", - "count", - "distinct", - "mapReduce", - "geoSearch", - "delete", - "find", - "killCursors", - "findAndModify", - "insert", - "update", - "create", - "drop", - "createIndexes", - "listIndexes")); - - private static String collectionName(CommandStartedEvent event) { - if (event.getCommandName().equals("getMore")) { - if (event.getCommand().containsKey("collection")) { - BsonValue collectionValue = event.getCommand().get("collection"); - if (collectionValue.isString()) { - return event.getCommand().getString("collection").getValue(); - } - } - } else if (COMMANDS_WITH_COLLECTION_NAME_AS_VALUE.contains(event.getCommandName())) { - BsonValue commandValue = event.getCommand().get(event.getCommandName()); - if (commandValue != null && commandValue.isString()) { - return commandValue.asString().getValue(); - } - } - return null; - } -} diff --git a/instrumentation/mongo/mongo-common/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/TracingCommandListener.java b/instrumentation/mongo/mongo-common/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/TracingCommandListener.java deleted file mode 100644 index 3ee04b2069..0000000000 --- a/instrumentation/mongo/mongo-common/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/TracingCommandListener.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.mongo; - -import static io.opentelemetry.javaagent.instrumentation.mongo.MongoClientTracer.tracer; - -import com.mongodb.event.CommandFailedEvent; -import com.mongodb.event.CommandListener; -import com.mongodb.event.CommandStartedEvent; -import com.mongodb.event.CommandSucceededEvent; -import io.opentelemetry.api.trace.Span; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class TracingCommandListener implements CommandListener { - - private final Map spanMap = new ConcurrentHashMap<>(); - - @Override - public void commandStarted(CommandStartedEvent event) { - Span span = tracer().startSpan(event, event.getCommand()); - spanMap.put(event.getRequestId(), span); - } - - @Override - public void commandSucceeded(CommandSucceededEvent event) { - Span span = spanMap.remove(event.getRequestId()); - if (span != null) { - tracer().end(span); - } - } - - @Override - public void commandFailed(CommandFailedEvent event) { - Span span = spanMap.remove(event.getRequestId()); - if (span != null) { - tracer().endExceptionally(span, event.getThrowable()); - } - } -} diff --git a/instrumentation/netty/netty-3.8/netty-3.8.gradle b/instrumentation/netty/netty-3.8/netty-3.8.gradle deleted file mode 100644 index 83210be660..0000000000 --- a/instrumentation/netty/netty-3.8/netty-3.8.gradle +++ /dev/null @@ -1,42 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" -apply plugin: 'org.unbroken-dome.test-sets' - -muzzle { - pass { - group = "io.netty" - module = "netty" - versions = "[3.8.0.Final,4)" - assertInverse = true - } - fail { - group = "io.netty" - module = "netty-all" - versions = "[,]" - } -} - -testSets { - latestDepTest -} - -dependencies { - compileOnly group: 'io.netty', name: 'netty', version: '3.8.0.Final' - - testImplementation group: 'io.netty', name: 'netty', version: '3.8.0.Final' - testImplementation group: 'com.ning', name: 'async-http-client', version: '1.8.0' - - latestDepTestImplementation group: 'io.netty', name: 'netty', version: '3.10.+' - latestDepTestImplementation group: 'com.ning', name: 'async-http-client', version: '1.9.+' -} - -// We need to force the dependency to the earliest supported version because other libraries declare newer versions. -configurations.testImplementation { - resolutionStrategy { - eachDependency { DependencyResolveDetails details -> - //specifying a fixed version for all libraries with io.netty' group - if (details.requested.group == 'io.netty') { - details.useVersion "3.8.0.Final" - } - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/latestDepTest/groovy/Netty38ClientTest.groovy b/instrumentation/netty/netty-3.8/src/latestDepTest/groovy/Netty38ClientTest.groovy deleted file mode 100644 index 2915a1c7fe..0000000000 --- a/instrumentation/netty/netty-3.8/src/latestDepTest/groovy/Netty38ClientTest.groovy +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.ning.http.client.AsyncCompletionHandler -import com.ning.http.client.AsyncHttpClient -import com.ning.http.client.AsyncHttpClientConfig -import com.ning.http.client.Response -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import spock.lang.AutoCleanup -import spock.lang.Shared - -class Netty38ClientTest extends HttpClientTest { - - @Shared - def clientConfig = new AsyncHttpClientConfig.Builder() - .setRequestTimeout(TimeUnit.SECONDS.toMillis(10).toInteger()) - .build() - - @Shared - @AutoCleanup - AsyncHttpClient asyncHttpClient = new AsyncHttpClient(clientConfig) - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def methodName = "prepare" + method.toLowerCase().capitalize() - def requestBuilder = asyncHttpClient."$methodName"(uri.toString()) - headers.each { requestBuilder.setHeader(it.key, it.value) } - def response = requestBuilder.execute(new AsyncCompletionHandler() { - @Override - Object onCompleted(Response response) throws Exception { - callback?.call() - return response - } - }).get() - return response.statusCode - } - - @Override - String userAgent() { - return "AHC" - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } - - def "connection error (unopened port)"() { - given: - def uri = new URI("http://127.0.0.1:$UNUSABLE_PORT/") - - when: - runUnderTrace("parent") { - doRequest(method, uri) - } - - then: - def ex = thrown(Exception) - def thrownException = ex instanceof ExecutionException ? ex.cause : ex - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent", null, thrownException) - - span(1) { - name "CONNECT" - childOf span(0) - errored true - Class errorClass = ConnectException - try { - errorClass = Class.forName('io.netty.channel.AbstractChannel$AnnotatedConnectException') - } catch (ClassNotFoundException e) { - // Older versions use 'java.net.ConnectException' and do not have 'io.netty.channel.AbstractChannel$AnnotatedConnectException' - } - errorEvent(errorClass, ~/Connection refused:( no further information:)? \/127.0.0.1:$UNUSABLE_PORT/) - } - } - } - - where: - method = "GET" - } -} diff --git a/instrumentation/netty/netty-3.8/src/latestDepTest/groovy/Netty38ServerTest.groovy b/instrumentation/netty/netty-3.8/src/latestDepTest/groovy/Netty38ServerTest.groovy deleted file mode 100644 index 06367800e6..0000000000 --- a/instrumentation/netty/netty-3.8/src/latestDepTest/groovy/Netty38ServerTest.groovy +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.forPath -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.LOCATION -import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1 - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import org.jboss.netty.bootstrap.ServerBootstrap -import org.jboss.netty.buffer.ChannelBuffer -import org.jboss.netty.buffer.ChannelBuffers -import org.jboss.netty.channel.ChannelHandlerContext -import org.jboss.netty.channel.ChannelPipeline -import org.jboss.netty.channel.ChannelPipelineFactory -import org.jboss.netty.channel.DefaultChannelPipeline -import org.jboss.netty.channel.DownstreamMessageEvent -import org.jboss.netty.channel.ExceptionEvent -import org.jboss.netty.channel.FailedChannelFuture -import org.jboss.netty.channel.MessageEvent -import org.jboss.netty.channel.SimpleChannelHandler -import org.jboss.netty.channel.SucceededChannelFuture -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory -import org.jboss.netty.handler.codec.http.DefaultHttpResponse -import org.jboss.netty.handler.codec.http.HttpRequest -import org.jboss.netty.handler.codec.http.HttpResponse -import org.jboss.netty.handler.codec.http.HttpResponseStatus -import org.jboss.netty.handler.codec.http.HttpServerCodec -import org.jboss.netty.handler.logging.LoggingHandler -import org.jboss.netty.logging.InternalLogLevel -import org.jboss.netty.logging.InternalLoggerFactory -import org.jboss.netty.logging.Slf4JLoggerFactory -import org.jboss.netty.util.CharsetUtil - -class Netty38ServerTest extends HttpServerTest { - - static final LoggingHandler LOGGING_HANDLER - static { - InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()) - LOGGING_HANDLER = new LoggingHandler(SERVER_LOGGER.name, InternalLogLevel.DEBUG, true) - } - - ChannelPipeline channelPipeline() { - ChannelPipeline channelPipeline = new DefaultChannelPipeline() - channelPipeline.addFirst("logger", LOGGING_HANDLER) - - channelPipeline.addLast("http-codec", new HttpServerCodec()) - channelPipeline.addLast("controller", new SimpleChannelHandler() { - @Override - void messageReceived(ChannelHandlerContext ctx, MessageEvent msg) throws Exception { - if (msg.getMessage() instanceof HttpRequest) { - def uri = URI.create((msg.getMessage() as HttpRequest).getUri()) - HttpServerTest.ServerEndpoint endpoint = forPath(uri.path) - ctx.sendDownstream controller(endpoint) { - HttpResponse response - ChannelBuffer responseContent = null - switch (endpoint) { - case SUCCESS: - case ERROR: - responseContent = ChannelBuffers.copiedBuffer(endpoint.body, CharsetUtil.UTF_8) - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.setContent(responseContent) - break - case QUERY_PARAM: - responseContent = ChannelBuffers.copiedBuffer(uri.query, CharsetUtil.UTF_8) - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.setContent(responseContent) - break - case REDIRECT: - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.headers().set(LOCATION, endpoint.body) - break - case EXCEPTION: - throw new Exception(endpoint.body) - default: - responseContent = ChannelBuffers.copiedBuffer(NOT_FOUND.body, CharsetUtil.UTF_8) - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.setContent(responseContent) - break - } - response.headers().set(CONTENT_TYPE, "text/plain") - if (responseContent) { - response.headers().set(CONTENT_LENGTH, responseContent.readableBytes()) - } - return new DownstreamMessageEvent( - ctx.getChannel(), - new SucceededChannelFuture(ctx.getChannel()), - response, - ctx.getChannel().getRemoteAddress()) - } - } - } - - @Override - void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent ex) throws Exception { - def message = ex.getCause() == null ? " " + ex.message : ex.cause.message == null ? "" : ex.cause.message - ChannelBuffer buffer = ChannelBuffers.copiedBuffer(message, CharsetUtil.UTF_8) - HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR) - response.setContent(buffer) - response.headers().set(CONTENT_TYPE, "text/plain") - response.headers().set(CONTENT_LENGTH, buffer.readableBytes()) - ctx.sendDownstream(new DownstreamMessageEvent( - ctx.getChannel(), - new FailedChannelFuture(ctx.getChannel(), ex.getCause()), - response, - ctx.getChannel().getRemoteAddress())) - } - }) - - return channelPipeline - } - - @Override - ServerBootstrap startServer(int port) { - ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory()) - bootstrap.setParentHandler(LOGGING_HANDLER) - bootstrap.setPipelineFactory(new ChannelPipelineFactory() { - @Override - ChannelPipeline getPipeline() throws Exception { - return channelPipeline() - } - }) - - InetSocketAddress address = new InetSocketAddress(port) - bootstrap.bind(address) - return bootstrap - } - - @Override - void stopServer(ServerBootstrap server) { - server?.shutdown() - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "netty.request" - } - - @Override - boolean testException() { - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/807 - return false - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/ChannelFutureListenerInstrumentation.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/ChannelFutureListenerInstrumentation.java deleted file mode 100644 index 940d074e7d..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/ChannelFutureListenerInstrumentation.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyHttpClientTracer; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelFuture; - -public class ChannelFutureListenerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.jboss.netty.channel.ChannelFutureListener"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.jboss.netty.channel.ChannelFutureListener")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("operationComplete")) - .and(takesArgument(0, named("org.jboss.netty.channel.ChannelFuture"))), - ChannelFutureListenerInstrumentation.class.getName() + "$OperationCompleteAdvice"); - } - - public static class OperationCompleteAdvice { - @Advice.OnMethodEnter - public static Scope activateScope(@Advice.Argument(0) ChannelFuture future) { - /* - Idea here is: - - To return scope only if we have captured it. - - To capture scope only in case of error. - */ - Throwable cause = future.getCause(); - if (cause == null) { - return null; - } - - ContextStore contextStore = - InstrumentationContext.get(Channel.class, ChannelTraceContext.class); - - Context parentContext = - contextStore - .putIfAbsent(future.getChannel(), ChannelTraceContext.Factory.INSTANCE) - .getConnectionContext(); - contextStore.get(future.getChannel()).setConnectionContext(null); - if (parentContext == null) { - return null; - } - // TODO pass Context into Tracer.startSpan() and then don't need this scoping - Scope parentScope = parentContext.makeCurrent(); - Span errorSpan = NettyHttpClientTracer.tracer().startSpan("CONNECT", Kind.CLIENT); - NettyHttpClientTracer.tracer().endExceptionally(errorSpan, cause); - return parentScope; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void deactivateScope(@Advice.Enter Scope scope) { - if (scope != null) { - scope.close(); - } - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/ChannelTraceContext.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/ChannelTraceContext.java deleted file mode 100644 index b2465b660b..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/ChannelTraceContext.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import java.util.Objects; - -public class ChannelTraceContext { - public static class Factory implements ContextStore.Factory { - public static final Factory INSTANCE = new Factory(); - - @Override - public ChannelTraceContext create() { - return new ChannelTraceContext(); - } - } - - private Context connectionContext; - private Span clientSpan; - private Context clientParentContext; - private Context context; - - public Context getConnectionContext() { - return connectionContext; - } - - public void setConnectionContext(Context connectionContinuation) { - this.connectionContext = connectionContinuation; - } - - public Span getClientSpan() { - return clientSpan; - } - - public void setClientSpan(Span clientSpan) { - this.clientSpan = clientSpan; - } - - public Context getClientParentContext() { - return clientParentContext; - } - - public void setClientParentContext(Context clientParentContext) { - this.clientParentContext = clientParentContext; - } - - public Context getContext() { - return context; - } - - public void setContext(Context context) { - this.context = context; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof ChannelTraceContext)) { - return false; - } - ChannelTraceContext other = (ChannelTraceContext) obj; - return Objects.equals(connectionContext, other.connectionContext) - && Objects.equals(clientSpan, other.clientSpan) - && Objects.equals(clientParentContext, other.clientParentContext) - && Objects.equals(context, other.context); - } - - @Override - public int hashCode() { - return Objects.hash(connectionContext, clientSpan, clientParentContext, context); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java deleted file mode 100644 index 698a978c34..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.jboss.netty.channel.Channel; - -public class NettyChannelInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.jboss.netty.channel.Channel"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.jboss.netty.channel.Channel")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(named("connect")) - .and(returns(named("org.jboss.netty.channel.ChannelFuture"))), - NettyChannelInstrumentation.class.getName() + "$ChannelConnectAdvice"); - return transformers; - } - - public static class ChannelConnectAdvice { - @Advice.OnMethodEnter - public static void addConnectContinuation(@Advice.This Channel channel) { - Context context = Java8BytecodeBridge.currentContext(); - Span span = Java8BytecodeBridge.spanFromContext(context); - if (span.getSpanContext().isValid()) { - ContextStore contextStore = - InstrumentationContext.get(Channel.class, ChannelTraceContext.class); - - if (contextStore - .putIfAbsent(channel, ChannelTraceContext.Factory.INSTANCE) - .getConnectionContext() - == null) { - contextStore.get(channel).setConnectionContext(context); - } - } - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelPipelineInstrumentation.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelPipelineInstrumentation.java deleted file mode 100644 index 5de1e6eba1..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelPipelineInstrumentation.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.HttpClientRequestTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.HttpClientResponseTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.HttpClientTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.HttpServerRequestTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.HttpServerResponseTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.HttpServerTracingHandler; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandler; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.handler.codec.http.HttpClientCodec; -import org.jboss.netty.handler.codec.http.HttpRequestDecoder; -import org.jboss.netty.handler.codec.http.HttpRequestEncoder; -import org.jboss.netty.handler.codec.http.HttpResponseDecoder; -import org.jboss.netty.handler.codec.http.HttpResponseEncoder; -import org.jboss.netty.handler.codec.http.HttpServerCodec; - -public class NettyChannelPipelineInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("org.jboss.netty.channel.ChannelPipeline"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("org.jboss.netty.channel.ChannelPipeline")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(nameStartsWith("add")) - .and(takesArgument(1, named("org.jboss.netty.channel.ChannelHandler"))), - NettyChannelPipelineInstrumentation.class.getName() + "$ChannelPipelineAdd2ArgsAdvice"); - transformers.put( - isMethod() - .and(nameStartsWith("add")) - .and(takesArgument(2, named("org.jboss.netty.channel.ChannelHandler"))), - NettyChannelPipelineInstrumentation.class.getName() + "$ChannelPipelineAdd3ArgsAdvice"); - return transformers; - } - - /** - * When certain handlers are added to the pipeline, we want to add our corresponding tracing - * handlers. If those handlers are later removed, we may want to remove our handlers. That is not - * currently implemented. - */ - public static class ChannelPipelineAdviceUtil { - public static void wrapHandler( - ContextStore contextStore, - ChannelPipeline pipeline, - ChannelHandler handler) { - try { - // Server pipeline handlers - if (handler instanceof HttpServerCodec) { - pipeline.addLast( - HttpServerTracingHandler.class.getName(), new HttpServerTracingHandler(contextStore)); - } else if (handler instanceof HttpRequestDecoder) { - pipeline.addLast( - HttpServerRequestTracingHandler.class.getName(), - new HttpServerRequestTracingHandler(contextStore)); - } else if (handler instanceof HttpResponseEncoder) { - pipeline.addLast( - HttpServerResponseTracingHandler.class.getName(), - new HttpServerResponseTracingHandler(contextStore)); - } else - // Client pipeline handlers - if (handler instanceof HttpClientCodec) { - pipeline.addLast( - HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler(contextStore)); - } else if (handler instanceof HttpRequestEncoder) { - pipeline.addLast( - HttpClientRequestTracingHandler.class.getName(), - new HttpClientRequestTracingHandler(contextStore)); - } else if (handler instanceof HttpResponseDecoder) { - pipeline.addLast( - HttpClientResponseTracingHandler.class.getName(), - new HttpClientResponseTracingHandler(contextStore)); - } - } finally { - CallDepthThreadLocalMap.reset(ChannelPipeline.class); - } - } - } - - public static class ChannelPipelineAdd2ArgsAdvice { - @Advice.OnMethodEnter - public static int checkDepth( - @Advice.This ChannelPipeline pipeline, @Advice.Argument(1) ChannelHandler handler) { - // Pipelines are created once as a factory and then copied multiple times using the same add - // methods as we are hooking. If our handler has already been added we need to remove it so we - // don't end up with duplicates (this throws an exception) - if (pipeline.get(handler.getClass().getName()) != null) { - pipeline.remove(handler.getClass().getName()); - } - return CallDepthThreadLocalMap.incrementCallDepth(ChannelPipeline.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void addHandler( - @Advice.Enter int depth, - @Advice.This ChannelPipeline pipeline, - @Advice.Argument(1) ChannelHandler handler) { - if (depth > 0) { - return; - } - - ContextStore contextStore = - InstrumentationContext.get(Channel.class, ChannelTraceContext.class); - - ChannelPipelineAdviceUtil.wrapHandler(contextStore, pipeline, handler); - } - } - - public static class ChannelPipelineAdd3ArgsAdvice { - @Advice.OnMethodEnter - public static int checkDepth( - @Advice.This ChannelPipeline pipeline, @Advice.Argument(2) ChannelHandler handler) { - // Pipelines are created once as a factory and then copied multiple times using the same add - // methods as we are hooking. If our handler has already been added we need to remove it so we - // don't end up with duplicates (this throws an exception) - if (pipeline.get(handler.getClass().getName()) != null) { - pipeline.remove(handler.getClass().getName()); - } - return CallDepthThreadLocalMap.incrementCallDepth(ChannelPipeline.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void addHandler( - @Advice.Enter int depth, - @Advice.This ChannelPipeline pipeline, - @Advice.Argument(2) ChannelHandler handler) { - if (depth > 0) { - return; - } - - ContextStore contextStore = - InstrumentationContext.get(Channel.class, ChannelTraceContext.class); - - ChannelPipelineAdviceUtil.wrapHandler(contextStore, pipeline, handler); - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java deleted file mode 100644 index 9fae920d9b..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class NettyInstrumentationModule extends InstrumentationModule { - public NettyInstrumentationModule() { - super("netty", "netty-3.8"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ChannelFutureListenerInstrumentation(), - new NettyChannelInstrumentation(), - new NettyChannelPipelineInstrumentation()); - } - - @Override - public Map contextStore() { - return Collections.singletonMap( - "org.jboss.netty.channel.Channel", ChannelTraceContext.class.getName()); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientRequestTracingHandler.java deleted file mode 100644 index 65147851c7..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientRequestTracingHandler.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyHttpClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import java.net.InetSocketAddress; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.channel.SimpleChannelDownstreamHandler; -import org.jboss.netty.handler.codec.http.HttpRequest; - -public class HttpClientRequestTracingHandler extends SimpleChannelDownstreamHandler { - - private final ContextStore contextStore; - - public HttpClientRequestTracingHandler(ContextStore contextStore) { - this.contextStore = contextStore; - } - - @Override - public void writeRequested(ChannelHandlerContext ctx, MessageEvent msg) { - if (!(msg.getMessage() instanceof HttpRequest)) { - ctx.sendDownstream(msg); - return; - } - - ChannelTraceContext channelTraceContext = - contextStore.putIfAbsent(ctx.getChannel(), ChannelTraceContext.Factory.INSTANCE); - - // TODO pass Context into Tracer.startSpan() and then don't need this scoping - Scope parentScope = null; - Context parentContext = channelTraceContext.getConnectionContext(); - if (parentContext != null) { - parentScope = parentContext.makeCurrent(); - channelTraceContext.setConnectionContext(null); - } - channelTraceContext.setClientParentContext(Context.current()); - - HttpRequest request = (HttpRequest) msg.getMessage(); - - Span span = tracer().startSpan(request); - NetPeerUtils.setNetPeer(span, (InetSocketAddress) ctx.getChannel().getRemoteAddress()); - channelTraceContext.setClientSpan(span); - - try (Scope ignored = tracer().startScope(span, request.headers())) { - ctx.sendDownstream(msg); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } finally { - if (parentScope != null) { - parentScope.close(); - } - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientResponseTracingHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientResponseTracingHandler.java deleted file mode 100644 index ca7c7a7cf1..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientResponseTracingHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyHttpClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.channel.SimpleChannelUpstreamHandler; -import org.jboss.netty.handler.codec.http.HttpResponse; - -public class HttpClientResponseTracingHandler extends SimpleChannelUpstreamHandler { - - private final ContextStore contextStore; - - public HttpClientResponseTracingHandler(ContextStore contextStore) { - this.contextStore = contextStore; - } - - @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent msg) { - ChannelTraceContext channelTraceContext = - contextStore.putIfAbsent(ctx.getChannel(), ChannelTraceContext.Factory.INSTANCE); - - Context parentContext = channelTraceContext.getClientParentContext(); - Span span = channelTraceContext.getClientSpan(); - - boolean finishSpan = msg.getMessage() instanceof HttpResponse; - - if (span != null && finishSpan) { - tracer().end(span, (HttpResponse) msg.getMessage()); - } - - // We want the callback in the scope of the parent, not the client span - if (parentContext != null) { - try (Scope ignored = parentContext.makeCurrent()) { - ctx.sendUpstream(msg); - } - } else { - ctx.sendUpstream(msg); - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientTracingHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientTracingHandler.java deleted file mode 100644 index de6474c839..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/HttpClientTracingHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; - -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.util.CombinedSimpleChannelHandler; -import org.jboss.netty.channel.Channel; - -public class HttpClientTracingHandler - extends CombinedSimpleChannelHandler< - HttpClientResponseTracingHandler, HttpClientRequestTracingHandler> { - - public HttpClientTracingHandler(ContextStore contextStore) { - super( - new HttpClientResponseTracingHandler(contextStore), - new HttpClientRequestTracingHandler(contextStore)); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyHttpClientTracer.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyHttpClientTracer.java deleted file mode 100644 index 2cb9f3dfbf..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyHttpClientTracer.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyResponseInjectAdapter.SETTER; -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.HOST; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.jboss.netty.handler.codec.http.HttpHeaders; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpResponse; - -public class NettyHttpClientTracer - extends HttpClientTracer { - private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer(); - - public static NettyHttpClientTracer tracer() { - return TRACER; - } - - @Override - public Scope startScope(Span span, HttpHeaders headers) { - if (!headers.contains("amz-sdk-invocation-id")) { - return super.startScope(span, headers); - } else { - // TODO (trask) if we move injection up to aws-sdk layer, and start suppressing nested netty - // spans, do we still need this condition? - // AWS calls are often signed, so we can't add headers without breaking the signature. - Context context = Context.current().with(span); - context = context.with(CONTEXT_CLIENT_SPAN_KEY, span); - return context.makeCurrent(); - } - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.getMethod().getName(); - } - - @Override - protected @Nullable String flavor(HttpRequest httpRequest) { - return httpRequest.getProtocolVersion().getText(); - } - - @Override - protected URI url(HttpRequest request) throws URISyntaxException { - URI uri = new URI(request.getUri()); - if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) { - return new URI("http://" + request.headers().get(HOST) + request.getUri()); - } else { - return uri; - } - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.getStatus().getCode(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().get(name); - } - - @Override - protected String responseHeader(HttpResponse httpResponse, String name) { - return httpResponse.headers().get(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.netty"; - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyResponseInjectAdapter.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyResponseInjectAdapter.java deleted file mode 100644 index 2d2ebca6b6..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyResponseInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.jboss.netty.handler.codec.http.HttpHeaders; - -public class NettyResponseInjectAdapter implements TextMapPropagator.Setter { - - public static final NettyResponseInjectAdapter SETTER = new NettyResponseInjectAdapter(); - - @Override - public void set(HttpHeaders headers, String key, String value) { - headers.set(key, value); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerRequestTracingHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerRequestTracingHandler.java deleted file mode 100644 index 2e2b91a61d..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerRequestTracingHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server; - -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.NettyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.channel.SimpleChannelUpstreamHandler; -import org.jboss.netty.handler.codec.http.HttpRequest; - -public class HttpServerRequestTracingHandler extends SimpleChannelUpstreamHandler { - - private final ContextStore contextStore; - - public HttpServerRequestTracingHandler(ContextStore contextStore) { - this.contextStore = contextStore; - } - - @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent msg) { - ChannelTraceContext channelTraceContext = - contextStore.putIfAbsent(ctx.getChannel(), ChannelTraceContext.Factory.INSTANCE); - - if (!(msg.getMessage() instanceof HttpRequest)) { - Context serverContext = tracer().getServerContext(channelTraceContext); - if (serverContext == null) { - ctx.sendUpstream(msg); - } else { - try (Scope ignored = serverContext.makeCurrent()) { - ctx.sendUpstream(msg); - } - } - return; - } - - HttpRequest request = (HttpRequest) msg.getMessage(); - - Context context = tracer().startSpan(request, ctx.getChannel(), "netty.request"); - Span span = Java8BytecodeBridge.spanFromContext(context); - try (Scope ignored = tracer().startScope(span, channelTraceContext)) { - ctx.sendUpstream(msg); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerResponseTracingHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerResponseTracingHandler.java deleted file mode 100644 index 43573cc9c8..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerResponseTracingHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server; - -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.NettyHttpServerTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.channel.SimpleChannelDownstreamHandler; -import org.jboss.netty.handler.codec.http.HttpResponse; - -public class HttpServerResponseTracingHandler extends SimpleChannelDownstreamHandler { - - private final ContextStore contextStore; - - public HttpServerResponseTracingHandler(ContextStore contextStore) { - this.contextStore = contextStore; - } - - @Override - public void writeRequested(ChannelHandlerContext ctx, MessageEvent msg) { - ChannelTraceContext channelTraceContext = - contextStore.putIfAbsent(ctx.getChannel(), ChannelTraceContext.Factory.INSTANCE); - - Context context = tracer().getServerContext(channelTraceContext); - if (context == null || !(msg.getMessage() instanceof HttpResponse)) { - ctx.sendDownstream(msg); - return; - } - - Span span = Span.fromContext(context); - try (Scope ignored = context.makeCurrent()) { - ctx.sendDownstream(msg); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } - tracer().end(span, (HttpResponse) msg.getMessage()); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerTracingHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerTracingHandler.java deleted file mode 100644 index b733cd9c65..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/HttpServerTracingHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server; - -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.util.CombinedSimpleChannelHandler; -import org.jboss.netty.channel.Channel; - -public class HttpServerTracingHandler - extends CombinedSimpleChannelHandler< - HttpServerRequestTracingHandler, HttpServerResponseTracingHandler> { - - public HttpServerTracingHandler(ContextStore contextStore) { - super( - new HttpServerRequestTracingHandler(contextStore), - new HttpServerResponseTracingHandler(contextStore)); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHttpServerTracer.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHttpServerTracer.java deleted file mode 100644 index c0a521191e..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHttpServerTracer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server; - -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.HOST; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer; -import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpResponse; - -public class NettyHttpServerTracer - extends HttpServerTracer { - private static final NettyHttpServerTracer TRACER = new NettyHttpServerTracer(); - - public static NettyHttpServerTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.getMethod().getName(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().get(name); - } - - @Override - protected int responseStatus(HttpResponse httpResponse) { - return httpResponse.getStatus().getCode(); - } - - @Override - protected void attachServerContext(Context context, ChannelTraceContext channelTraceContext) { - channelTraceContext.setContext(context); - } - - @Override - public Context getServerContext(ChannelTraceContext channelTraceContext) { - return channelTraceContext.getContext(); - } - - @Override - protected String url(HttpRequest request) { - String uri = request.getUri(); - if (isRelativeUrl(uri) && request.headers().contains(HOST)) { - return "http://" + request.headers().get(HOST) + request.getUri(); - } else { - return uri; - } - } - - @Override - protected String peerHostIP(Channel channel) { - SocketAddress socketAddress = channel.getRemoteAddress(); - if (socketAddress instanceof InetSocketAddress) { - return ((InetSocketAddress) socketAddress).getAddress().getHostAddress(); - } - return null; - } - - @Override - protected String flavor(Channel channel, HttpRequest request) { - return request.getProtocolVersion().toString(); - } - - @Override - protected Getter getGetter() { - return NettyRequestExtractAdapter.GETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.netty"; - } - - @Override - protected Integer peerPort(Channel channel) { - SocketAddress socketAddress = channel.getRemoteAddress(); - if (socketAddress instanceof InetSocketAddress) { - return ((InetSocketAddress) socketAddress).getPort(); - } - return null; - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyRequestExtractAdapter.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyRequestExtractAdapter.java deleted file mode 100644 index dcb7421c9b..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyRequestExtractAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import org.jboss.netty.handler.codec.http.HttpRequest; - -public class NettyRequestExtractAdapter implements TextMapPropagator.Getter { - - public static final NettyRequestExtractAdapter GETTER = new NettyRequestExtractAdapter(); - - @Override - public Iterable keys(HttpRequest request) { - return request.headers().names(); - } - - @Override - public String get(HttpRequest request, String key) { - return request.headers().get(key); - } -} diff --git a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/util/CombinedSimpleChannelHandler.java b/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/util/CombinedSimpleChannelHandler.java deleted file mode 100644 index 5fb3fba4fd..0000000000 --- a/instrumentation/netty/netty-3.8/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/util/CombinedSimpleChannelHandler.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v3_8.util; - -import org.jboss.netty.channel.ChannelEvent; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.ChildChannelStateEvent; -import org.jboss.netty.channel.ExceptionEvent; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.channel.SimpleChannelDownstreamHandler; -import org.jboss.netty.channel.SimpleChannelHandler; -import org.jboss.netty.channel.SimpleChannelUpstreamHandler; -import org.jboss.netty.channel.WriteCompletionEvent; - -public class CombinedSimpleChannelHandler< - UPSTREAM extends SimpleChannelUpstreamHandler, - DOWNSTREAM extends SimpleChannelDownstreamHandler> - extends SimpleChannelHandler { - - private final UPSTREAM upstream; - private final DOWNSTREAM downstream; - - public CombinedSimpleChannelHandler(UPSTREAM upstream, DOWNSTREAM downstream) { - this.upstream = upstream; - this.downstream = downstream; - } - - @Override - public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception { - upstream.handleUpstream(ctx, e); - } - - @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - upstream.messageReceived(ctx, e); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { - upstream.exceptionCaught(ctx, e); - } - - @Override - public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - upstream.channelOpen(ctx, e); - } - - @Override - public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - upstream.channelBound(ctx, e); - } - - @Override - public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - upstream.channelConnected(ctx, e); - } - - @Override - public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) - throws Exception { - upstream.channelInterestChanged(ctx, e); - } - - @Override - public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - upstream.channelDisconnected(ctx, e); - } - - @Override - public void channelUnbound(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - upstream.channelUnbound(ctx, e); - } - - @Override - public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - upstream.channelClosed(ctx, e); - } - - @Override - public void writeComplete(ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception { - upstream.writeComplete(ctx, e); - } - - @Override - public void childChannelOpen(ChannelHandlerContext ctx, ChildChannelStateEvent e) - throws Exception { - upstream.childChannelOpen(ctx, e); - } - - @Override - public void childChannelClosed(ChannelHandlerContext ctx, ChildChannelStateEvent e) - throws Exception { - upstream.childChannelClosed(ctx, e); - } - - @Override - public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception { - downstream.handleDownstream(ctx, e); - } - - @Override - public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - downstream.writeRequested(ctx, e); - } - - @Override - public void bindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - downstream.bindRequested(ctx, e); - } - - @Override - public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - downstream.connectRequested(ctx, e); - } - - @Override - public void setInterestOpsRequested(ChannelHandlerContext ctx, ChannelStateEvent e) - throws Exception { - downstream.setInterestOpsRequested(ctx, e); - } - - @Override - public void disconnectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - downstream.disconnectRequested(ctx, e); - } - - @Override - public void unbindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - downstream.unbindRequested(ctx, e); - } - - @Override - public void closeRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - downstream.closeRequested(ctx, e); - } -} diff --git a/instrumentation/netty/netty-3.8/src/test/groovy/Netty38ClientTest.groovy b/instrumentation/netty/netty-3.8/src/test/groovy/Netty38ClientTest.groovy deleted file mode 100644 index 0523040ad5..0000000000 --- a/instrumentation/netty/netty-3.8/src/test/groovy/Netty38ClientTest.groovy +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.ning.http.client.AsyncCompletionHandler -import com.ning.http.client.AsyncHttpClient -import com.ning.http.client.AsyncHttpClientConfig -import com.ning.http.client.Response -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import spock.lang.AutoCleanup -import spock.lang.Shared - -class Netty38ClientTest extends HttpClientTest { - - @Shared - def clientConfig = new AsyncHttpClientConfig.Builder() - .setRequestTimeoutInMs(TimeUnit.SECONDS.toMillis(10).toInteger()) - .build() - - @Shared - @AutoCleanup - AsyncHttpClient asyncHttpClient = new AsyncHttpClient(clientConfig) - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def methodName = "prepare" + method.toLowerCase().capitalize() - def requestBuilder = asyncHttpClient."$methodName"(uri.toString()) - headers.each { requestBuilder.setHeader(it.key, it.value) } - def response = requestBuilder.execute(new AsyncCompletionHandler() { - @Override - Object onCompleted(Response response) throws Exception { - callback?.call() - return response - } - }).get() - return response.statusCode - } - - @Override - String userAgent() { - return "NING" - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } - - def "connection error (unopened port)"() { - given: - def uri = new URI("http://127.0.0.1:$UNUSABLE_PORT/") - - when: - runUnderTrace("parent") { - doRequest(method, uri) - } - - then: - def ex = thrown(Exception) - def thrownException = ex instanceof ExecutionException ? ex.cause : ex - - and: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent", null, thrownException) - - span(1) { - name "CONNECT" - childOf span(0) - errored true - Class errorClass = ConnectException - try { - errorClass = Class.forName('io.netty.channel.AbstractChannel$AnnotatedConnectException') - } catch (ClassNotFoundException e) { - // Older versions use 'java.net.ConnectException' and do not have 'io.netty.channel.AbstractChannel$AnnotatedConnectException' - } - errorEvent(errorClass, ~/Connection refused:( no further information:)? \/127.0.0.1:$UNUSABLE_PORT/) - } - } - } - - where: - method = "GET" - } -} diff --git a/instrumentation/netty/netty-3.8/src/test/groovy/Netty38ServerTest.groovy b/instrumentation/netty/netty-3.8/src/test/groovy/Netty38ServerTest.groovy deleted file mode 100644 index bb77939728..0000000000 --- a/instrumentation/netty/netty-3.8/src/test/groovy/Netty38ServerTest.groovy +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.forPath -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE -import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.LOCATION -import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1 - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import org.jboss.netty.bootstrap.ServerBootstrap -import org.jboss.netty.buffer.ChannelBuffer -import org.jboss.netty.buffer.ChannelBuffers -import org.jboss.netty.channel.ChannelHandlerContext -import org.jboss.netty.channel.ChannelPipeline -import org.jboss.netty.channel.ChannelPipelineFactory -import org.jboss.netty.channel.DefaultChannelPipeline -import org.jboss.netty.channel.DownstreamMessageEvent -import org.jboss.netty.channel.ExceptionEvent -import org.jboss.netty.channel.FailedChannelFuture -import org.jboss.netty.channel.MessageEvent -import org.jboss.netty.channel.SimpleChannelHandler -import org.jboss.netty.channel.SucceededChannelFuture -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory -import org.jboss.netty.handler.codec.http.DefaultHttpResponse -import org.jboss.netty.handler.codec.http.HttpRequest -import org.jboss.netty.handler.codec.http.HttpResponse -import org.jboss.netty.handler.codec.http.HttpResponseStatus -import org.jboss.netty.handler.codec.http.HttpServerCodec -import org.jboss.netty.handler.logging.LoggingHandler -import org.jboss.netty.logging.InternalLogLevel -import org.jboss.netty.logging.InternalLoggerFactory -import org.jboss.netty.logging.Slf4JLoggerFactory -import org.jboss.netty.util.CharsetUtil - -class Netty38ServerTest extends HttpServerTest { - - static final LoggingHandler LOGGING_HANDLER - static { - InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()) - LOGGING_HANDLER = new LoggingHandler(SERVER_LOGGER.name, InternalLogLevel.DEBUG, true) - } - - ChannelPipeline channelPipeline() { - ChannelPipeline channelPipeline = new DefaultChannelPipeline() - channelPipeline.addFirst("logger", LOGGING_HANDLER) - - channelPipeline.addLast("http-codec", new HttpServerCodec()) - channelPipeline.addLast("controller", new SimpleChannelHandler() { - @Override - void messageReceived(ChannelHandlerContext ctx, MessageEvent msg) throws Exception { - if (msg.getMessage() instanceof HttpRequest) { - def uri = URI.create((msg.getMessage() as HttpRequest).getUri()) - HttpServerTest.ServerEndpoint endpoint = forPath(uri.path) - ctx.sendDownstream controller(endpoint) { - HttpResponse response - ChannelBuffer responseContent = null - switch (endpoint) { - case SUCCESS: - case ERROR: - responseContent = ChannelBuffers.copiedBuffer(endpoint.body, CharsetUtil.UTF_8) - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.setContent(responseContent) - break - case QUERY_PARAM: - responseContent = ChannelBuffers.copiedBuffer(uri.query, CharsetUtil.UTF_8) - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.setContent(responseContent) - break - case REDIRECT: - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.headers().set(LOCATION, endpoint.body) - break - case EXCEPTION: - throw new Exception(endpoint.body) - default: - responseContent = ChannelBuffers.copiedBuffer(NOT_FOUND.body, CharsetUtil.UTF_8) - response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.setContent(responseContent) - break - } - response.headers().set(CONTENT_TYPE, "text/plain") - if (responseContent) { - response.headers().set(CONTENT_LENGTH, responseContent.readableBytes()) - } - return new DownstreamMessageEvent( - ctx.getChannel(), - new SucceededChannelFuture(ctx.getChannel()), - response, - ctx.getChannel().getRemoteAddress()) - } - } - } - - @Override - void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent ex) throws Exception { - def message = ex.cause == null ? " " + ex.message : ex.cause.message == null ? "" : ex.cause.message - ChannelBuffer buffer = ChannelBuffers.copiedBuffer(message, CharsetUtil.UTF_8) - HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR) - response.setContent(buffer) - response.headers().set(CONTENT_TYPE, "text/plain") - response.headers().set(CONTENT_LENGTH, buffer.readableBytes()) - ctx.sendDownstream(new DownstreamMessageEvent( - ctx.getChannel(), - new FailedChannelFuture(ctx.getChannel(), ex.getCause()), - response, - ctx.getChannel().getRemoteAddress())) - } - }) - - return channelPipeline - } - - @Override - ServerBootstrap startServer(int port) { - ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory()) - bootstrap.setParentHandler(LOGGING_HANDLER) - bootstrap.setPipelineFactory(new ChannelPipelineFactory() { - @Override - ChannelPipeline getPipeline() throws Exception { - return channelPipeline() - } - }) - - InetSocketAddress address = new InetSocketAddress(port) - bootstrap.bind(address) - return bootstrap - } - - @Override - void stopServer(ServerBootstrap server) { - server?.shutdown() - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "netty.request" - } - - @Override - boolean testException() { - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/807 - return false - } -} diff --git a/instrumentation/netty/netty-4.0/netty-4.0.gradle b/instrumentation/netty/netty-4.0/netty-4.0.gradle deleted file mode 100644 index d88476fa8b..0000000000 --- a/instrumentation/netty/netty-4.0/netty-4.0.gradle +++ /dev/null @@ -1,48 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.netty" - module = "netty-codec-http" - versions = "[4.0.0.Final,4.1.0.Final)" - assertInverse = true - } - pass { - group = "io.netty" - module = "netty-all" - versions = "[4.0.0.Final,4.1.0.Final)" - assertInverse = true - } - fail { - group = "io.netty" - module = "netty" - versions = "[,]" - } - pass { - group = "io.vertx" - module = "vertx-core" - versions = "[2.0.0,3.3.0)" - assertInverse = true - } -} - -dependencies { - library group: 'io.netty', name: 'netty-codec-http', version: '4.0.0.Final' - - testLibrary group: 'org.asynchttpclient', name: 'async-http-client', version: '2.0.9' - - latestDepTestLibrary group: 'io.netty', name: 'netty-codec-http', version: '4.0.56.Final' - latestDepTestLibrary group: 'org.asynchttpclient', name: 'async-http-client', version: '2.0.+' -} - -// We need to force the dependency to the earliest supported version because other libraries declare newer versions. -configurations.testImplementation { - resolutionStrategy { - eachDependency { DependencyResolveDetails details -> - //specifying a fixed version for all libraries with io.netty' group - if (details.requested.group == 'io.netty') { - details.useVersion "4.0.0.Final" - } - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/AttributeKeys.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/AttributeKeys.java deleted file mode 100644 index 33f8846792..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/AttributeKeys.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0; - -import io.netty.util.AttributeKey; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.WeakMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public class AttributeKeys { - private static final WeakMap>> map = - WeakMap.Implementation.DEFAULT.get(); - private static final WeakMap.ValueSupplier>> - mapSupplier = - new WeakMap.ValueSupplier>>() { - @Override - public ConcurrentMap> get(ClassLoader ignore) { - return new ConcurrentHashMap<>(); - } - }; - - public static final AttributeKey CONNECT_CONTEXT = - attributeKey(AttributeKeys.class.getName() + ".connect-context"); - - // this is the context that has the server span - public static final AttributeKey SERVER_SPAN = - attributeKey(AttributeKeys.class.getName() + ".server-span"); - - public static final AttributeKey CLIENT_SPAN = - attributeKey(AttributeKeys.class.getName() + ".client-span"); - - public static final AttributeKey CLIENT_PARENT_CONTEXT = - attributeKey(AttributeKeys.class.getName() + ".client-parent-context"); - - /** - * Generate an attribute key or reuse the one existing in the global app map. This implementation - * creates attributes only once even if the current class is loaded by several class loaders and - * prevents an issue with Apache Atlas project were this class loaded by multiple class loaders, - * while the Attribute class is loaded by a third class loader and used internally for the - * cassandra driver. - */ - private static AttributeKey attributeKey(String key) { - ConcurrentMap> classLoaderMap = - map.computeIfAbsent(AttributeKey.class.getClassLoader(), mapSupplier); - if (classLoaderMap.containsKey(key)) { - return (AttributeKey) classLoaderMap.get(key); - } - - AttributeKey value = new AttributeKey<>(key); - classLoaderMap.put(key, value); - return value; - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/ChannelFutureListenerInstrumentation.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/ChannelFutureListenerInstrumentation.java deleted file mode 100644 index f5a542b9c4..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/ChannelFutureListenerInstrumentation.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.netty.channel.ChannelFuture; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.NettyHttpClientTracer; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class ChannelFutureListenerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("io.netty.channel.ChannelFutureListener"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("io.netty.channel.ChannelFutureListener")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("operationComplete")) - .and(takesArgument(0, named("io.netty.channel.ChannelFuture"))), - ChannelFutureListenerInstrumentation.class.getName() + "$OperationCompleteAdvice"); - } - - public static class OperationCompleteAdvice { - @Advice.OnMethodEnter - public static Scope activateScope(@Advice.Argument(0) ChannelFuture future) { - /* - Idea here is: - - To return scope only if we have captured it. - - To capture scope only in case of error. - */ - Throwable cause = future.cause(); - if (cause == null) { - return null; - } - Context parentContext = future.channel().attr(AttributeKeys.CONNECT_CONTEXT).getAndRemove(); - if (parentContext == null) { - return null; - } - Scope parentScope = parentContext.makeCurrent(); - Span span = NettyHttpClientTracer.tracer().startSpan("CONNECT", Kind.CLIENT); - NettyHttpClientTracer.tracer().endExceptionally(span, cause); - return parentScope; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void deactivateScope(@Advice.Enter Scope scope) { - if (scope != null) { - scope.close(); - } - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/NettyChannelPipelineInstrumentation.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/NettyChannelPipelineInstrumentation.java deleted file mode 100644 index 02d09d1064..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/NettyChannelPipelineInstrumentation.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpRequestDecoder; -import io.netty.handler.codec.http.HttpRequestEncoder; -import io.netty.handler.codec.http.HttpResponseDecoder; -import io.netty.handler.codec.http.HttpResponseEncoder; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.util.Attribute; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.HttpClientRequestTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.HttpClientResponseTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.HttpClientTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.server.HttpServerRequestTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.server.HttpServerResponseTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.server.HttpServerTracingHandler; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class NettyChannelPipelineInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("io.netty.channel.ChannelPipeline"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("io.netty.channel.ChannelPipeline")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(nameStartsWith("add")) - .and(takesArgument(2, named("io.netty.channel.ChannelHandler"))), - NettyChannelPipelineInstrumentation.class.getName() + "$ChannelPipelineAddAdvice"); - transformers.put( - isMethod().and(named("connect")).and(returns(named("io.netty.channel.ChannelFuture"))), - NettyChannelPipelineInstrumentation.class.getName() + "$ChannelPipelineConnectAdvice"); - return transformers; - } - - /** - * When certain handlers are added to the pipeline, we want to add our corresponding tracing - * handlers. If those handlers are later removed, we may want to remove our handlers. That is not - * currently implemented. - */ - public static class ChannelPipelineAddAdvice { - @Advice.OnMethodEnter - public static int trackCallDepth() { - return CallDepthThreadLocalMap.incrementCallDepth(ChannelPipeline.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void addHandler( - @Advice.Enter int callDepth, - @Advice.This ChannelPipeline pipeline, - @Advice.Argument(2) ChannelHandler handler) { - if (callDepth > 0) { - return; - } - CallDepthThreadLocalMap.reset(ChannelPipeline.class); - - try { - // Server pipeline handlers - if (handler instanceof HttpServerCodec) { - pipeline.addLast( - HttpServerTracingHandler.class.getName(), new HttpServerTracingHandler()); - } else if (handler instanceof HttpRequestDecoder) { - pipeline.addLast( - HttpServerRequestTracingHandler.class.getName(), - new HttpServerRequestTracingHandler()); - } else if (handler instanceof HttpResponseEncoder) { - pipeline.addLast( - HttpServerResponseTracingHandler.class.getName(), - new HttpServerResponseTracingHandler()); - } else - // Client pipeline handlers - if (handler instanceof HttpClientCodec) { - pipeline.addLast( - HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler()); - } else if (handler instanceof HttpRequestEncoder) { - pipeline.addLast( - HttpClientRequestTracingHandler.class.getName(), - new HttpClientRequestTracingHandler()); - } else if (handler instanceof HttpResponseDecoder) { - pipeline.addLast( - HttpClientResponseTracingHandler.class.getName(), - new HttpClientResponseTracingHandler()); - } - } catch (IllegalArgumentException e) { - // Prevented adding duplicate handlers. - } - } - } - - public static class ChannelPipelineConnectAdvice { - @Advice.OnMethodEnter - public static void addParentSpan(@Advice.This ChannelPipeline pipeline) { - Context context = Java8BytecodeBridge.currentContext(); - Attribute attribute = pipeline.channel().attr(AttributeKeys.CONNECT_CONTEXT); - attribute.compareAndSet(null, context); - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/NettyInstrumentationModule.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/NettyInstrumentationModule.java deleted file mode 100644 index d5229e2964..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/NettyInstrumentationModule.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class NettyInstrumentationModule extends InstrumentationModule { - public NettyInstrumentationModule() { - super("netty", "netty-4.0"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ChannelFutureListenerInstrumentation(), new NettyChannelPipelineInstrumentation()); - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientRequestTracingHandler.java deleted file mode 100644 index c4b3875c02..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientRequestTracingHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.NettyHttpClientTracer.tracer; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys; -import java.net.InetSocketAddress; - -public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter { - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) { - if (!(msg instanceof HttpRequest)) { - ctx.write(msg, prm); - return; - } - - // TODO pass Context into Tracer.startSpan() and then don't need this scoping - Scope parentScope = null; - Context parentContext = ctx.channel().attr(AttributeKeys.CONNECT_CONTEXT).getAndRemove(); - if (parentContext != null) { - parentScope = parentContext.makeCurrent(); - } - - HttpRequest request = (HttpRequest) msg; - - ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(Context.current()); - - Span span = tracer().startSpan(request); - NetPeerUtils.setNetPeer(span, (InetSocketAddress) ctx.channel().remoteAddress()); - ctx.channel().attr(AttributeKeys.CLIENT_SPAN).set(span); - - try (Scope scope = tracer().startScope(span, request.headers())) { - ctx.write(msg, prm); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } finally { - if (null != parentScope) { - parentScope.close(); - } - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientResponseTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientResponseTracingHandler.java deleted file mode 100644 index 370557aaf1..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientResponseTracingHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.NettyHttpClientTracer.tracer; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.util.Attribute; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys; - -public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapter { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - Attribute parentAttr = ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT); - Context parentContext = parentAttr.get(); - Span span = ctx.channel().attr(AttributeKeys.CLIENT_SPAN).get(); - - boolean finishSpan = msg instanceof HttpResponse; - - if (span != null && finishSpan) { - tracer().end(span, (HttpResponse) msg); - } - - // We want the callback in the scope of the parent, not the client span - if (parentContext != null) { - try (Scope ignored = parentContext.makeCurrent()) { - ctx.fireChannelRead(msg); - } - } else { - ctx.fireChannelRead(msg); - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientTracingHandler.java deleted file mode 100644 index 332b560727..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/HttpClientTracingHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client; - -import io.netty.channel.CombinedChannelDuplexHandler; - -public class HttpClientTracingHandler - extends CombinedChannelDuplexHandler< - HttpClientResponseTracingHandler, HttpClientRequestTracingHandler> { - - public HttpClientTracingHandler() { - super(new HttpClientResponseTracingHandler(), new HttpClientRequestTracingHandler()); - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyHttpClientTracer.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyHttpClientTracer.java deleted file mode 100644 index aabf6ddbfb..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyHttpClientTracer.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client; - -import static io.netty.handler.codec.http.HttpHeaders.Names.HOST; -import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.NettyResponseInjectAdapter.SETTER; - -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; -import org.checkerframework.checker.nullness.qual.Nullable; - -public class NettyHttpClientTracer - extends HttpClientTracer { - private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer(); - - public static NettyHttpClientTracer tracer() { - return TRACER; - } - - @Override - public Scope startScope(Span span, HttpHeaders headers) { - if (!headers.contains("amz-sdk-invocation-id")) { - return super.startScope(span, headers); - } else { - // TODO (trask) if we move injection up to aws-sdk layer, and start suppressing nested netty - // spans, do we still need this condition? - // AWS calls are often signed, so we can't add headers without breaking the signature. - Context context = Context.current().with(span); - context = context.with(CONTEXT_CLIENT_SPAN_KEY, span); - return context.makeCurrent(); - } - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.getMethod().name(); - } - - @Override - protected @Nullable String flavor(HttpRequest httpRequest) { - return httpRequest.getProtocolVersion().text(); - } - - @Override - protected URI url(HttpRequest request) throws URISyntaxException { - URI uri = new URI(request.getUri()); - if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) { - return new URI("http://" + request.headers().get(HOST) + request.getUri()); - } else { - return uri; - } - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.getStatus().code(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().get(name); - } - - @Override - protected String responseHeader(HttpResponse httpResponse, String name) { - return httpResponse.headers().get(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.netty"; - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyResponseInjectAdapter.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyResponseInjectAdapter.java deleted file mode 100644 index 297a99a9c7..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyResponseInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client; - -import io.netty.handler.codec.http.HttpHeaders; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class NettyResponseInjectAdapter implements TextMapPropagator.Setter { - - public static final NettyResponseInjectAdapter SETTER = new NettyResponseInjectAdapter(); - - @Override - public void set(HttpHeaders headers, String key, String value) { - headers.set(key, value); - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerRequestTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerRequestTracingHandler.java deleted file mode 100644 index ca791a052b..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerRequestTracingHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.server.NettyHttpServerTracer.tracer; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; - -public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - Channel channel = ctx.channel(); - - if (!(msg instanceof HttpRequest)) { - Context serverContext = tracer().getServerContext(channel); - if (serverContext == null) { - ctx.fireChannelRead(msg); - } else { - try (Scope ignored = serverContext.makeCurrent()) { - ctx.fireChannelRead(msg); - } - } - return; - } - - Context context = tracer().startSpan((HttpRequest) msg, channel, "netty.request"); - Span span = Java8BytecodeBridge.spanFromContext(context); - try (Scope ignored = tracer().startScope(span, channel)) { - ctx.fireChannelRead(msg); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerResponseTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerResponseTracingHandler.java deleted file mode 100644 index 519cdab5b6..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerResponseTracingHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.server.NettyHttpServerTracer.tracer; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; - -public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdapter { - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) { - Context context = tracer().getServerContext(ctx.channel()); - if (context == null || !(msg instanceof HttpResponse)) { - ctx.write(msg, prm); - return; - } - - Span span = Span.fromContext(context); - try (Scope ignored = context.makeCurrent()) { - ctx.write(msg, prm); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } - tracer().end(span, (HttpResponse) msg); - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerTracingHandler.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerTracingHandler.java deleted file mode 100644 index b77be55903..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/HttpServerTracingHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server; - -import io.netty.channel.CombinedChannelDuplexHandler; - -public class HttpServerTracingHandler - extends CombinedChannelDuplexHandler< - HttpServerRequestTracingHandler, HttpServerResponseTracingHandler> { - - public HttpServerTracingHandler() { - super(new HttpServerRequestTracingHandler(), new HttpServerResponseTracingHandler()); - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyHttpServerTracer.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyHttpServerTracer.java deleted file mode 100644 index 16e929ae05..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyHttpServerTracer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server; - -import static io.netty.handler.codec.http.HttpHeaders.Names.HOST; - -import io.netty.channel.Channel; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer; -import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -public class NettyHttpServerTracer - extends HttpServerTracer { - private static final NettyHttpServerTracer TRACER = new NettyHttpServerTracer(); - - public static NettyHttpServerTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.getMethod().name(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().get(name); - } - - @Override - protected int responseStatus(HttpResponse httpResponse) { - return httpResponse.getStatus().code(); - } - - @Override - protected void attachServerContext(Context context, Channel channel) { - channel.attr(AttributeKeys.SERVER_SPAN).set(context); - } - - @Override - public Context getServerContext(Channel channel) { - return channel.attr(AttributeKeys.SERVER_SPAN).get(); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.netty"; - } - - @Override - protected Getter getGetter() { - return NettyRequestExtractAdapter.GETTER; - } - - @Override - protected String url(HttpRequest request) { - String uri = request.getUri(); - if (isRelativeUrl(uri) && request.headers().contains(HOST)) { - return "http://" + request.headers().get(HOST) + request.getUri(); - } else { - return uri; - } - } - - @Override - protected String peerHostIP(Channel channel) { - SocketAddress socketAddress = channel.remoteAddress(); - if (socketAddress instanceof InetSocketAddress) { - return ((InetSocketAddress) socketAddress).getAddress().getHostAddress(); - } - return null; - } - - @Override - protected String flavor(Channel channel, HttpRequest request) { - return request.getProtocolVersion().toString(); - } - - @Override - protected Integer peerPort(Channel channel) { - SocketAddress socketAddress = channel.remoteAddress(); - if (socketAddress instanceof InetSocketAddress) { - return ((InetSocketAddress) socketAddress).getPort(); - } - return null; - } -} diff --git a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyRequestExtractAdapter.java b/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyRequestExtractAdapter.java deleted file mode 100644 index 47230e9d1a..0000000000 --- a/instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyRequestExtractAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server; - -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class NettyRequestExtractAdapter implements TextMapPropagator.Getter { - - public static final NettyRequestExtractAdapter GETTER = new NettyRequestExtractAdapter(); - - @Override - public Iterable keys(HttpRequest request) { - return request.headers().names(); - } - - @Override - public String get(HttpRequest request, String key) { - return request.headers().get(key); - } -} diff --git a/instrumentation/netty/netty-4.0/src/test/groovy/Netty40ClientTest.groovy b/instrumentation/netty/netty-4.0/src/test/groovy/Netty40ClientTest.groovy deleted file mode 100644 index 45c0cf9892..0000000000 --- a/instrumentation/netty/netty-4.0/src/test/groovy/Netty40ClientTest.groovy +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.asynchttpclient.Dsl.asyncHttpClient - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import org.asynchttpclient.AsyncCompletionHandler -import org.asynchttpclient.AsyncHttpClient -import org.asynchttpclient.DefaultAsyncHttpClientConfig -import org.asynchttpclient.Response -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class Netty40ClientTest extends HttpClientTest { - - @Shared - def clientConfig = DefaultAsyncHttpClientConfig.Builder.newInstance().setRequestTimeout(TimeUnit.SECONDS.toMillis(10).toInteger()) - @Shared - @AutoCleanup - AsyncHttpClient asyncHttpClient = asyncHttpClient(clientConfig) - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def methodName = "prepare" + method.toLowerCase().capitalize() - def requestBuilder = asyncHttpClient."$methodName"(uri.toString()) - headers.each { requestBuilder.setHeader(it.key, it.value) } - def response = requestBuilder.execute(new AsyncCompletionHandler() { - @Override - Object onCompleted(Response response) throws Exception { - callback?.call() - return response - } - }).get() - return response.statusCode - } - - @Override - String userAgent() { - return "AHC" - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } - - def "connection error (unopened port)"() { - given: - def uri = new URI("http://127.0.0.1:$UNUSABLE_PORT/") // Use numeric address to avoid ipv4/ipv6 confusion - - when: - runUnderTrace("parent") { - doRequest(method, uri) - } - - then: - def ex = thrown(Exception) - def thrownException = ex instanceof ExecutionException ? ex.cause : ex - - and: - assertTraces(1) { - def size = traces[0].size() - trace(0, size) { - basicSpan(it, 0, "parent", null, thrownException) - - // AsyncHttpClient retries across multiple resolved IP addresses (e.g. 127.0.0.1 and 0:0:0:0:0:0:0:1) - // for up to a total of 10 seconds (default connection time limit) - for (def i = 1; i < size; i++) { - span(i) { - name "CONNECT" - childOf span(0) - errored true - Class errorClass = ConnectException - try { - errorClass = Class.forName('io.netty.channel.AbstractChannel$AnnotatedConnectException') - } catch (ClassNotFoundException e) { - // Older versions use 'java.net.ConnectException' and do not have 'io.netty.channel.AbstractChannel$AnnotatedConnectException' - } - errorEvent(errorClass, ~/Connection refused:( no further information:)? \/127.0.0.1:$UNUSABLE_PORT/) - } - } - } - } - - where: - method = "GET" - } -} diff --git a/instrumentation/netty/netty-4.0/src/test/groovy/Netty40ServerTest.groovy b/instrumentation/netty/netty-4.0/src/test/groovy/Netty40ServerTest.groovy deleted file mode 100644 index 488b4d12fe..0000000000 --- a/instrumentation/netty/netty-4.0/src/test/groovy/Netty40ServerTest.groovy +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH -import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE -import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR -import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1 -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.netty.bootstrap.ServerBootstrap -import io.netty.buffer.ByteBuf -import io.netty.buffer.Unpooled -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelInitializer -import io.netty.channel.ChannelPipeline -import io.netty.channel.EventLoopGroup -import io.netty.channel.SimpleChannelInboundHandler -import io.netty.channel.nio.NioEventLoopGroup -import io.netty.channel.socket.nio.NioServerSocketChannel -import io.netty.handler.codec.http.DefaultFullHttpResponse -import io.netty.handler.codec.http.FullHttpResponse -import io.netty.handler.codec.http.HttpHeaders -import io.netty.handler.codec.http.HttpRequest -import io.netty.handler.codec.http.HttpRequestDecoder -import io.netty.handler.codec.http.HttpResponseEncoder -import io.netty.handler.codec.http.HttpResponseStatus -import io.netty.handler.logging.LogLevel -import io.netty.handler.logging.LoggingHandler -import io.netty.util.CharsetUtil -import io.opentelemetry.instrumentation.test.base.HttpServerTest - -class Netty40ServerTest extends HttpServerTest { - - static final LoggingHandler LOGGING_HANDLER = new LoggingHandler(SERVER_LOGGER.name, LogLevel.DEBUG) - - @Override - EventLoopGroup startServer(int port) { - def eventLoopGroup = new NioEventLoopGroup() - - ServerBootstrap bootstrap = new ServerBootstrap() - .group(eventLoopGroup) - .handler(LOGGING_HANDLER) - .childHandler([ - initChannel: { ch -> - ChannelPipeline pipeline = ch.pipeline() - pipeline.addFirst("logger", LOGGING_HANDLER) - - def handlers = [new HttpRequestDecoder(), new HttpResponseEncoder()] - handlers.each { pipeline.addLast(it) } - pipeline.addLast([ - channelRead0 : { ctx, msg -> - if (msg instanceof HttpRequest) { - def uri = URI.create((msg as HttpRequest).uri) - ServerEndpoint endpoint = ServerEndpoint.forPath(uri.path) - ctx.write controller(endpoint) { - ByteBuf content = null - FullHttpResponse response = null - switch (endpoint) { - case SUCCESS: - case ERROR: - content = Unpooled.copiedBuffer(endpoint.body, CharsetUtil.UTF_8) - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status), content) - break - case QUERY_PARAM: - content = Unpooled.copiedBuffer(uri.query, CharsetUtil.UTF_8) - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status), content) - break - case REDIRECT: - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.headers().set(HttpHeaders.Names.LOCATION, endpoint.body) - break - case EXCEPTION: - throw new Exception(endpoint.body) - default: - content = Unpooled.copiedBuffer(NOT_FOUND.body, CharsetUtil.UTF_8) - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(NOT_FOUND.status), content) - break - } - response.headers().set(CONTENT_TYPE, "text/plain") - if (content) { - response.headers().set(CONTENT_LENGTH, content.readableBytes()) - } - return response - } - } - }, - exceptionCaught : { ChannelHandlerContext ctx, Throwable cause -> - ByteBuf content = Unpooled.copiedBuffer(cause.message, CharsetUtil.UTF_8) - FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, INTERNAL_SERVER_ERROR, content) - response.headers().set(CONTENT_TYPE, "text/plain") - response.headers().set(CONTENT_LENGTH, content.readableBytes()) - ctx.write(response) - }, - channelReadComplete: { it.flush() } - ] as SimpleChannelInboundHandler) - } - ] as ChannelInitializer).channel(NioServerSocketChannel) - bootstrap.bind(port).sync() - - return eventLoopGroup - } - - @Override - void stopServer(EventLoopGroup server) { - server?.shutdownGracefully() - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "netty.request" - } - - @Override - boolean testException() { - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/807 - return false - } -} diff --git a/instrumentation/netty/netty-4.1/netty-4.1.gradle b/instrumentation/netty/netty-4.1/netty-4.1.gradle deleted file mode 100644 index 99cb6d117f..0000000000 --- a/instrumentation/netty/netty-4.1/netty-4.1.gradle +++ /dev/null @@ -1,47 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.netty" - module = "netty-codec-http" - versions = "[4.1.0.Final,)" - assertInverse = true - } - pass { - group = "io.netty" - module = "netty-all" - versions = "[4.1.0.Final,)" - assertInverse = true - } - fail { - group = "io.netty" - module = "netty" - versions = "[,]" - } - pass { - group = "io.vertx" - module = "vertx-core" - versions = "[3.3.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'io.netty', name: 'netty-codec-http', version: '4.1.0.Final' - - testLibrary group: 'org.asynchttpclient', name: 'async-http-client', version: '2.1.0' - - latestDepTestLibrary group: 'io.netty', name: 'netty-codec-http', version: '(,5.0)' -} - -// We need to force the dependency to the earliest supported version because other libraries declare newer versions. -configurations.testImplementation { - resolutionStrategy { - eachDependency { DependencyResolveDetails details -> - //specifying a fixed version for all libraries with io.netty' group - if (details.requested.group == 'io.netty') { - details.useVersion "4.1.0.Final" - } - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/AttributeKeys.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/AttributeKeys.java deleted file mode 100644 index a122ab733b..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/AttributeKeys.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1; - -import io.netty.util.AttributeKey; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; - -public class AttributeKeys { - - public static final AttributeKey CONNECT_CONTEXT = - AttributeKey.valueOf(AttributeKeys.class, "connect-context"); - - // this is the context that has the server span - // - // note: this attribute key is also used by ratpack instrumentation - public static final AttributeKey SERVER_SPAN = - AttributeKey.valueOf(AttributeKeys.class, "server-span"); - - public static final AttributeKey CLIENT_SPAN = - AttributeKey.valueOf(AttributeKeys.class, "client-span"); - - public static final AttributeKey CLIENT_PARENT_CONTEXT = - AttributeKey.valueOf(AttributeKeys.class, "client-parent-context"); -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/ChannelFutureListenerInstrumentation.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/ChannelFutureListenerInstrumentation.java deleted file mode 100644 index d84dfd1118..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/ChannelFutureListenerInstrumentation.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.netty.channel.ChannelFuture; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyHttpClientTracer; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class ChannelFutureListenerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("io.netty.channel.ChannelFutureListener"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("io.netty.channel.ChannelFutureListener")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("operationComplete")) - .and(takesArgument(0, named("io.netty.channel.ChannelFuture"))), - ChannelFutureListenerInstrumentation.class.getName() + "$OperationCompleteAdvice"); - } - - public static class OperationCompleteAdvice { - @Advice.OnMethodEnter - public static Scope activateScope(@Advice.Argument(0) ChannelFuture future) { - /* - Idea here is: - - To return scope only if we have captured it. - - To capture scope only in case of error. - */ - Throwable cause = future.cause(); - if (cause == null) { - return null; - } - Context parentContext = future.channel().attr(AttributeKeys.CONNECT_CONTEXT).getAndRemove(); - if (parentContext == null) { - return null; - } - Scope parentScope = parentContext.makeCurrent(); - Span errorSpan = NettyHttpClientTracer.tracer().startSpan("CONNECT", Kind.CLIENT); - NettyHttpClientTracer.tracer().endExceptionally(errorSpan, cause); - return parentScope; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void deactivateScope(@Advice.Enter Scope scope) { - if (scope != null) { - scope.close(); - } - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyChannelPipelineInstrumentation.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyChannelPipelineInstrumentation.java deleted file mode 100644 index 5ee2e3cc90..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyChannelPipelineInstrumentation.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpRequestDecoder; -import io.netty.handler.codec.http.HttpRequestEncoder; -import io.netty.handler.codec.http.HttpResponseDecoder; -import io.netty.handler.codec.http.HttpResponseEncoder; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.util.Attribute; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientRequestTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientResponseTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.HttpServerRequestTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.HttpServerResponseTracingHandler; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.HttpServerTracingHandler; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class NettyChannelPipelineInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("io.netty.channel.ChannelPipeline"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("io.netty.channel.ChannelPipeline")); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod() - .and(nameStartsWith("add")) - .and(takesArgument(2, named("io.netty.channel.ChannelHandler"))), - NettyChannelPipelineInstrumentation.class.getName() + "$ChannelPipelineAddAdvice"); - transformers.put( - isMethod().and(named("connect")).and(returns(named("io.netty.channel.ChannelFuture"))), - NettyChannelPipelineInstrumentation.class.getName() + "$ChannelPipelineConnectAdvice"); - return transformers; - } - - /** - * When certain handlers are added to the pipeline, we want to add our corresponding tracing - * handlers. If those handlers are later removed, we may want to remove our handlers. That is not - * currently implemented. - */ - public static class ChannelPipelineAddAdvice { - @Advice.OnMethodEnter - public static int trackCallDepth(@Advice.Argument(2) ChannelHandler handler) { - // Previously we used one unique call depth tracker for all handlers, using - // ChannelPipeline.class as a key. - // The problem with this approach is that it does not work with netty's - // io.netty.channel.ChannelInitializer which provides an `initChannel` that can be used to - // `addLast` other handlers. In that case the depth would exceed 0 and handlers added from - // initializers would not be considered. - // Using the specific handler key instead of the generic ChannelPipeline.class will help us - // both to handle such cases and avoid adding our additional handlers in case of internal - // calls of `addLast` to other method overloads with a compatible signature. - return CallDepthThreadLocalMap.incrementCallDepth(handler.getClass()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void addHandler( - @Advice.Enter int callDepth, - @Advice.This ChannelPipeline pipeline, - @Advice.Argument(2) ChannelHandler handler) { - if (callDepth > 0) { - return; - } - CallDepthThreadLocalMap.reset(handler.getClass()); - - try { - // Server pipeline handlers - if (handler instanceof HttpServerCodec) { - pipeline.addLast( - HttpServerTracingHandler.class.getName(), new HttpServerTracingHandler()); - } else if (handler instanceof HttpRequestDecoder) { - pipeline.addLast( - HttpServerRequestTracingHandler.class.getName(), - new HttpServerRequestTracingHandler()); - } else if (handler instanceof HttpResponseEncoder) { - pipeline.addLast( - HttpServerResponseTracingHandler.class.getName(), - new HttpServerResponseTracingHandler()); - } else - // Client pipeline handlers - if (handler instanceof HttpClientCodec) { - pipeline.addLast( - HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler()); - } else if (handler instanceof HttpRequestEncoder) { - pipeline.addLast( - HttpClientRequestTracingHandler.class.getName(), - new HttpClientRequestTracingHandler()); - } else if (handler instanceof HttpResponseDecoder) { - pipeline.addLast( - HttpClientResponseTracingHandler.class.getName(), - new HttpClientResponseTracingHandler()); - } - } catch (IllegalArgumentException e) { - // Prevented adding duplicate handlers. - } - } - } - - public static class ChannelPipelineConnectAdvice { - @Advice.OnMethodEnter - public static void addParentSpan(@Advice.This ChannelPipeline pipeline) { - Attribute attribute = pipeline.channel().attr(AttributeKeys.CONNECT_CONTEXT); - attribute.compareAndSet(null, Java8BytecodeBridge.currentContext()); - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyInstrumentationModule.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyInstrumentationModule.java deleted file mode 100644 index 7d361449d5..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyInstrumentationModule.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class NettyInstrumentationModule extends InstrumentationModule { - public NettyInstrumentationModule() { - super("netty", "netty-4.1"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ChannelFutureListenerInstrumentation(), new NettyChannelPipelineInstrumentation()); - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientRequestTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientRequestTracingHandler.java deleted file mode 100644 index fb284b4c28..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientRequestTracingHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyHttpClientTracer.tracer; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys; -import java.net.InetSocketAddress; - -public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter { - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) { - if (!(msg instanceof HttpRequest)) { - ctx.write(msg, prm); - return; - } - - // TODO pass Context into Tracer.startSpan() and then don't need this scoping - Scope parentScope = null; - Context parentContext = ctx.channel().attr(AttributeKeys.CONNECT_CONTEXT).getAndRemove(); - if (parentContext != null) { - parentScope = parentContext.makeCurrent(); - } - - HttpRequest request = (HttpRequest) msg; - - ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).set(Context.current()); - - Span span = tracer().startSpan(request); - NetPeerUtils.setNetPeer(span, (InetSocketAddress) ctx.channel().remoteAddress()); - ctx.channel().attr(AttributeKeys.CLIENT_SPAN).set(span); - - try (Scope ignored = tracer().startScope(span, request.headers())) { - ctx.write(msg, prm); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } finally { - if (null != parentScope) { - parentScope.close(); - } - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientResponseTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientResponseTracingHandler.java deleted file mode 100644 index 959e3b0a7e..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientResponseTracingHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyHttpClientTracer.tracer; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.util.Attribute; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys; - -public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapter { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - Attribute parentAttr = ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT); - Context parentContext = parentAttr.get(); - Span span = ctx.channel().attr(AttributeKeys.CLIENT_SPAN).get(); - - boolean finishSpan = msg instanceof HttpResponse; - - if (span != null && finishSpan) { - tracer().end(span, (HttpResponse) msg); - } - - // We want the callback in the scope of the parent, not the client span - if (parentContext != null) { - try (Scope ignored = parentContext.makeCurrent()) { - ctx.fireChannelRead(msg); - } - } else { - ctx.fireChannelRead(msg); - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientTracingHandler.java deleted file mode 100644 index d549aa823a..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/HttpClientTracingHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client; - -import io.netty.channel.CombinedChannelDuplexHandler; - -public class HttpClientTracingHandler - extends CombinedChannelDuplexHandler< - HttpClientResponseTracingHandler, HttpClientRequestTracingHandler> { - - public HttpClientTracingHandler() { - super(new HttpClientResponseTracingHandler(), new HttpClientRequestTracingHandler()); - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyHttpClientTracer.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyHttpClientTracer.java deleted file mode 100644 index 89a869f6de..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyHttpClientTracer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client; - -import static io.netty.handler.codec.http.HttpHeaderNames.HOST; -import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyResponseInjectAdapter.SETTER; - -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; -import org.checkerframework.checker.nullness.qual.Nullable; - -public class NettyHttpClientTracer - extends HttpClientTracer { - private static final NettyHttpClientTracer TRACER = new NettyHttpClientTracer(); - - public static NettyHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.method().name(); - } - - @Override - protected @Nullable String flavor(HttpRequest httpRequest) { - return httpRequest.protocolVersion().text(); - } - - @Override - protected URI url(HttpRequest request) throws URISyntaxException { - URI uri = new URI(request.uri()); - if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) { - return new URI("http://" + request.headers().get(HOST) + request.uri()); - } else { - return uri; - } - } - - @Override - protected Integer status(HttpResponse httpResponse) { - return httpResponse.status().code(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().get(name); - } - - @Override - protected String responseHeader(HttpResponse httpResponse, String name) { - return httpResponse.headers().get(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.netty"; - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyResponseInjectAdapter.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyResponseInjectAdapter.java deleted file mode 100644 index 0bc60e021c..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyResponseInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client; - -import io.netty.handler.codec.http.HttpHeaders; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class NettyResponseInjectAdapter implements TextMapPropagator.Setter { - - public static final NettyResponseInjectAdapter SETTER = new NettyResponseInjectAdapter(); - - @Override - public void set(HttpHeaders headers, String key, String value) { - headers.set(key, value); - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerRequestTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerRequestTracingHandler.java deleted file mode 100644 index 4198d9c366..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerRequestTracingHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.NettyHttpServerTracer.tracer; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; - -public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter { - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) { - Channel channel = ctx.channel(); - - if (!(msg instanceof HttpRequest)) { - Context serverContext = tracer().getServerContext(channel); - if (serverContext == null) { - ctx.fireChannelRead(msg); - } else { - try (Scope ignored = serverContext.makeCurrent()) { - ctx.fireChannelRead(msg); - } - } - return; - } - - Context context = tracer().startSpan((HttpRequest) msg, channel, "netty.request"); - Span span = Java8BytecodeBridge.spanFromContext(context); - try (Scope ignored = tracer().startScope(span, channel)) { - ctx.fireChannelRead(msg); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerResponseTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerResponseTracingHandler.java deleted file mode 100644 index bae52fefc1..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerResponseTracingHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server; - -import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.NettyHttpServerTracer.tracer; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; - -public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdapter { - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) { - Context context = tracer().getServerContext(ctx.channel()); - if (context == null || !(msg instanceof HttpResponse)) { - ctx.write(msg, prm); - return; - } - - Span span = Span.fromContext(context); - try (Scope ignored = context.makeCurrent()) { - ctx.write(msg, prm); - } catch (Throwable throwable) { - tracer().endExceptionally(span, throwable); - throw throwable; - } - tracer().end(span, (HttpResponse) msg); - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerTracingHandler.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerTracingHandler.java deleted file mode 100644 index cdb1be0fc0..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/HttpServerTracingHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server; - -import io.netty.channel.CombinedChannelDuplexHandler; - -public class HttpServerTracingHandler - extends CombinedChannelDuplexHandler< - HttpServerRequestTracingHandler, HttpServerResponseTracingHandler> { - - public HttpServerTracingHandler() { - super(new HttpServerRequestTracingHandler(), new HttpServerResponseTracingHandler()); - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/NettyHttpServerTracer.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/NettyHttpServerTracer.java deleted file mode 100644 index ea4306bae2..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/NettyHttpServerTracer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server; - -import static io.netty.handler.codec.http.HttpHeaderNames.HOST; - -import io.netty.channel.Channel; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -public class NettyHttpServerTracer - extends HttpServerTracer { - private static final NettyHttpServerTracer TRACER = new NettyHttpServerTracer(); - - public static NettyHttpServerTracer tracer() { - return TRACER; - } - - @Override - protected String method(HttpRequest httpRequest) { - return httpRequest.method().name(); - } - - @Override - protected String requestHeader(HttpRequest httpRequest, String name) { - return httpRequest.headers().get(name); - } - - @Override - protected int responseStatus(HttpResponse httpResponse) { - return httpResponse.status().code(); - } - - @Override - protected void attachServerContext(Context context, Channel channel) { - channel.attr(AttributeKeys.SERVER_SPAN).set(context); - } - - @Override - public Context getServerContext(Channel channel) { - return channel.attr(AttributeKeys.SERVER_SPAN).get(); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.netty"; - } - - @Override - protected Getter getGetter() { - return NettyRequestExtractAdapter.GETTER; - } - - @Override - protected String url(HttpRequest request) { - String uri = request.uri(); - if (isRelativeUrl(uri) && request.headers().contains(HOST)) { - return "http://" + request.headers().get(HOST) + request.uri(); - } else { - return uri; - } - } - - @Override - protected String peerHostIP(Channel channel) { - SocketAddress socketAddress = channel.remoteAddress(); - if (socketAddress instanceof InetSocketAddress) { - return ((InetSocketAddress) socketAddress).getAddress().getHostAddress(); - } - return null; - } - - @Override - protected String flavor(Channel channel, HttpRequest request) { - return request.protocolVersion().toString(); - } - - @Override - protected Integer peerPort(Channel channel) { - SocketAddress socketAddress = channel.remoteAddress(); - if (socketAddress instanceof InetSocketAddress) { - return ((InetSocketAddress) socketAddress).getPort(); - } - return null; - } -} diff --git a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/NettyRequestExtractAdapter.java b/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/NettyRequestExtractAdapter.java deleted file mode 100644 index 7b399375d3..0000000000 --- a/instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/server/NettyRequestExtractAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server; - -import io.netty.handler.codec.http.HttpRequest; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class NettyRequestExtractAdapter implements TextMapPropagator.Getter { - - public static final NettyRequestExtractAdapter GETTER = new NettyRequestExtractAdapter(); - - @Override - public Iterable keys(HttpRequest request) { - return request.headers().names(); - } - - @Override - public String get(HttpRequest request, String key) { - return request.headers().get(key); - } -} diff --git a/instrumentation/netty/netty-4.1/src/test/groovy/Netty41ClientTest.groovy b/instrumentation/netty/netty-4.1/src/test/groovy/Netty41ClientTest.groovy deleted file mode 100644 index 418f1101d7..0000000000 --- a/instrumentation/netty/netty-4.1/src/test/groovy/Netty41ClientTest.groovy +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace -import static org.asynchttpclient.Dsl.asyncHttpClient - -import io.netty.bootstrap.Bootstrap -import io.netty.buffer.Unpooled -import io.netty.channel.AbstractChannel -import io.netty.channel.Channel -import io.netty.channel.ChannelHandler -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelInitializer -import io.netty.channel.ChannelPipeline -import io.netty.channel.EventLoopGroup -import io.netty.channel.embedded.EmbeddedChannel -import io.netty.channel.nio.NioEventLoopGroup -import io.netty.channel.socket.SocketChannel -import io.netty.channel.socket.nio.NioSocketChannel -import io.netty.handler.codec.http.DefaultFullHttpRequest -import io.netty.handler.codec.http.HttpClientCodec -import io.netty.handler.codec.http.HttpHeaderNames -import io.netty.handler.codec.http.HttpMethod -import io.netty.handler.codec.http.HttpVersion -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientTracingHandler -import java.util.concurrent.ExecutionException -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException -import org.asynchttpclient.AsyncCompletionHandler -import org.asynchttpclient.AsyncHttpClient -import org.asynchttpclient.DefaultAsyncHttpClientConfig -import org.asynchttpclient.Response -import spock.lang.Ignore -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class Netty41ClientTest extends HttpClientTest { - - @Shared - def clientConfig = DefaultAsyncHttpClientConfig.Builder.newInstance().setRequestTimeout(TimeUnit.SECONDS.toMillis(10).toInteger()) - @Shared - AsyncHttpClient asyncHttpClient = asyncHttpClient(clientConfig) - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def methodName = "prepare" + method.toLowerCase().capitalize() - def requestBuilder = asyncHttpClient."$methodName"(uri.toString()) - headers.each { requestBuilder.setHeader(it.key, it.value) } - def response = requestBuilder.execute(new AsyncCompletionHandler() { - @Override - Object onCompleted(Response response) throws Exception { - callback?.call() - return response - } - }).get() - return response.statusCode - } - - @Override - String userAgent() { - return "AHC" - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } - - @Ignore("this test currently fails. See https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1312") - def "test connection interference"() { - setup: - //Create a simple Netty pipeline - EventLoopGroup group = new NioEventLoopGroup() - Bootstrap b = new Bootstrap() - b.group(group) - .channel(NioSocketChannel) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel socketChannel) throws Exception { - ChannelPipeline pipeline = socketChannel.pipeline() - pipeline.addLast(new HttpClientCodec()) - } - }) - - //Important! Separate connect, outside of any request - Channel ch = b.connect(server.address.host, server.address.port).sync().channel() - - def request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, server.address.resolve("/success").toString(), Unpooled.EMPTY_BUFFER) - request.headers().set(HttpHeaderNames.HOST, server.address.host) - request.headers().set(HttpHeaderNames.USER_AGENT, userAgent()) - - when: - runUnderTrace("parent1") { - ch.writeAndFlush(request).get() - } - runUnderTrace("parent2") { - ch.writeAndFlush(request).get() - } - - then: - assertTraces(2) { - trace(0, 3) { - basicSpan(it, 0, "parent1") - clientSpan(it, 1, span(0)) - serverSpan(it, 2, span(1)) - } - trace(1, 3) { - basicSpan(it, 0, "parent2") - clientSpan(it, 1, span(0)) - serverSpan(it, 2, span(1)) - } - } - cleanup: - group.shutdownGracefully() - } - - - def "test connection reuse and second request with lazy execute"() { - setup: - //Create a simple Netty pipeline - EventLoopGroup group = new NioEventLoopGroup() - Bootstrap b = new Bootstrap() - b.group(group) - .channel(NioSocketChannel) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel socketChannel) throws Exception { - ChannelPipeline pipeline = socketChannel.pipeline() - pipeline.addLast(new HttpClientCodec()) - } - }) - def request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, server.address.resolve("/success").toString(), Unpooled.EMPTY_BUFFER) - request.headers().set(HttpHeaderNames.HOST, server.address.host) - request.headers().set(HttpHeaderNames.USER_AGENT, userAgent()) - Channel ch = null - - when: - // note that this is a purely asynchronous request - runUnderTrace("parent1") { - ch = b.connect(server.address.host, server.address.port).sync().channel() - ch.write(request) - ch.flush() - } - // This is a cheap/easy way to block/ensure that the first request has finished and check reported spans midway through - // the complex sequence of events - assertTraces(1) { - trace(0, 3) { - basicSpan(it, 0, "parent1") - clientSpan(it, 1, span(0)) - serverSpan(it, 2, span(1)) - } - } - - then: - // now run a second request through the same channel - runUnderTrace("parent2") { - ch.write(request) - ch.flush() - } - - assertTraces(2) { - trace(0, 3) { - basicSpan(it, 0, "parent1") - clientSpan(it, 1, span(0)) - serverSpan(it, 2, span(1)) - } - trace(1, 3) { - basicSpan(it, 0, "parent2") - clientSpan(it, 1, span(0)) - serverSpan(it, 2, span(1)) - } - } - - - cleanup: - group.shutdownGracefully() - } - - def "connection error (unopened port)"() { - given: - def uri = new URI("http://localhost:$UNUSABLE_PORT/") - - when: - runUnderTrace("parent") { - doRequest(method, uri) - } - - then: - def ex = thrown(Exception) - ex.cause instanceof ConnectException || ex.cause instanceof TimeoutException - def thrownException = ex instanceof ExecutionException ? ex.cause : ex - - and: - assertTraces(1) { - def size = traces[0].size() - trace(0, size) { - basicSpan(it, 0, "parent", null, thrownException) - - // AsyncHttpClient retries across multiple resolved IP addresses (e.g. 127.0.0.1 and 0:0:0:0:0:0:0:1) - // for up to a total of 10 seconds (default connection time limit) - for (def i = 1; i < size; i++) { - span(i) { - name "CONNECT" - childOf span(0) - errored true - errorEvent(AbstractChannel.AnnotatedConnectException, ~/Connection refused:( no further information:)? localhost\/\[?[0-9.:]+\]?:$UNUSABLE_PORT/) - } - } - } - } - - where: - method = "GET" - } - - def "when a handler is added to the netty pipeline we add our tracing handler"() { - setup: - def channel = new EmbeddedChannel() - def pipeline = channel.pipeline() - - when: - pipeline.addLast("name", new HttpClientCodec()) - - then: - // The first one returns the removed tracing handler - pipeline.remove(HttpClientTracingHandler.getName()) != null - } - - def "when a handler is added to the netty pipeline we add ONLY ONE tracing handler"() { - setup: - def channel = new EmbeddedChannel() - def pipeline = channel.pipeline() - - when: - pipeline.addLast("name", new HttpClientCodec()) - // The first one returns the removed tracing handler - pipeline.remove(HttpClientTracingHandler.getName()) - // There is only one - pipeline.remove(HttpClientTracingHandler.getName()) == null - - then: - thrown NoSuchElementException - } - - def "handlers of different types can be added"() { - setup: - def channel = new EmbeddedChannel() - def pipeline = channel.pipeline() - - when: - pipeline.addLast("some_handler", new SimpleHandler()) - pipeline.addLast("a_traced_handler", new HttpClientCodec()) - - then: - // The first one returns the removed tracing handler - null != pipeline.remove(HttpClientTracingHandler.getName()) - null != pipeline.remove("some_handler") - null != pipeline.remove("a_traced_handler") - } - - def "calling pipeline.addLast methods that use overloaded methods does not cause infinite loop"() { - setup: - def channel = new EmbeddedChannel() - - when: - channel.pipeline().addLast(new SimpleHandler(), new OtherSimpleHandler()) - - then: - null != channel.pipeline().remove('Netty41ClientTest$SimpleHandler#0') - null != channel.pipeline().remove('Netty41ClientTest$OtherSimpleHandler#0') - } - - def "when a traced handler is added from an initializer we still detect it and add our channel handlers"() { - // This test method replicates a scenario similar to how reactor 0.8.x register the `HttpClientCodec` handler - // into the pipeline. - - setup: - def channel = new EmbeddedChannel() - - when: - channel.pipeline().addLast(new TracedHandlerFromInitializerHandler()) - - then: - null != channel.pipeline().remove("added_in_initializer") - null != channel.pipeline().remove(HttpClientTracingHandler.getName()) - } - - def "request with trace annotated method"() { - given: - def annotatedClass = new TracedClass() - - when: - def status = runUnderTrace("parent") { - annotatedClass.tracedMethod(method) - } - - then: - status == 200 - assertTraces(1) { - trace(0, 4) { - basicSpan(it, 0, "parent") - span(1) { - childOf span(0) - name "tracedMethod" - errored false - attributes { - } - } - clientSpan(it, 2, span(1), method) - server.distributedRequestSpan(it, 3, span(2)) - } - } - - where: - method << BODY_METHODS - } - - class TracedClass { - int tracedMethod(String method) { - runUnderTrace("tracedMethod") { - doRequest(method, server.address.resolve("/success")) - } - } - } - - static class SimpleHandler implements ChannelHandler { - @Override - void handlerAdded(ChannelHandlerContext ctx) throws Exception { - } - - @Override - void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - } - - @Override - void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - } - } - - static class OtherSimpleHandler implements ChannelHandler { - @Override - void handlerAdded(ChannelHandlerContext ctx) throws Exception { - } - - @Override - void handlerRemoved(ChannelHandlerContext ctx) throws Exception { - } - - @Override - void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - } - } - - static class TracedHandlerFromInitializerHandler extends ChannelInitializer implements ChannelHandler { - @Override - protected void initChannel(Channel ch) throws Exception { - // This replicates how reactor 0.8.x add the HttpClientCodec - ch.pipeline().addLast("added_in_initializer", new HttpClientCodec()) - } - } -} diff --git a/instrumentation/netty/netty-4.1/src/test/groovy/Netty41ServerTest.groovy b/instrumentation/netty/netty-4.1/src/test/groovy/Netty41ServerTest.groovy deleted file mode 100644 index 78f7b984ab..0000000000 --- a/instrumentation/netty/netty-4.1/src/test/groovy/Netty41ServerTest.groovy +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH -import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE -import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR -import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1 -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.NOT_FOUND -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.netty.bootstrap.ServerBootstrap -import io.netty.buffer.ByteBuf -import io.netty.buffer.Unpooled -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelInitializer -import io.netty.channel.ChannelPipeline -import io.netty.channel.EventLoopGroup -import io.netty.channel.SimpleChannelInboundHandler -import io.netty.channel.nio.NioEventLoopGroup -import io.netty.channel.socket.nio.NioServerSocketChannel -import io.netty.handler.codec.http.DefaultFullHttpResponse -import io.netty.handler.codec.http.FullHttpResponse -import io.netty.handler.codec.http.HttpHeaderNames -import io.netty.handler.codec.http.HttpRequest -import io.netty.handler.codec.http.HttpResponseStatus -import io.netty.handler.codec.http.HttpServerCodec -import io.netty.handler.logging.LogLevel -import io.netty.handler.logging.LoggingHandler -import io.netty.util.CharsetUtil -import io.opentelemetry.instrumentation.test.base.HttpServerTest - -class Netty41ServerTest extends HttpServerTest { - - static final LoggingHandler LOGGING_HANDLER = new LoggingHandler(SERVER_LOGGER.name, LogLevel.DEBUG) - - @Override - EventLoopGroup startServer(int port) { - def eventLoopGroup = new NioEventLoopGroup() - - ServerBootstrap bootstrap = new ServerBootstrap() - .group(eventLoopGroup) - .handler(LOGGING_HANDLER) - .childHandler([ - initChannel: { ch -> - ChannelPipeline pipeline = ch.pipeline() - pipeline.addFirst("logger", LOGGING_HANDLER) - - def handlers = [new HttpServerCodec()] - handlers.each { pipeline.addLast(it) } - pipeline.addLast([ - channelRead0 : { ctx, msg -> - if (msg instanceof HttpRequest) { - def uri = URI.create((msg as HttpRequest).uri) - ServerEndpoint endpoint = ServerEndpoint.forPath(uri.path) - ctx.write controller(endpoint) { - ByteBuf content = null - FullHttpResponse response = null - switch (endpoint) { - case SUCCESS: - case ERROR: - content = Unpooled.copiedBuffer(endpoint.body, CharsetUtil.UTF_8) - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status), content) - break - case QUERY_PARAM: - content = Unpooled.copiedBuffer(uri.query, CharsetUtil.UTF_8) - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status), content) - break - case REDIRECT: - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(endpoint.status)) - response.headers().set(HttpHeaderNames.LOCATION, endpoint.body) - break - case EXCEPTION: - throw new Exception(endpoint.body) - default: - content = Unpooled.copiedBuffer(NOT_FOUND.body, CharsetUtil.UTF_8) - response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.valueOf(NOT_FOUND.status), content) - break - } - response.headers().set(CONTENT_TYPE, "text/plain") - if (content) { - response.headers().set(CONTENT_LENGTH, content.readableBytes()) - } - return response - } - } - }, - exceptionCaught : { ChannelHandlerContext ctx, Throwable cause -> - ByteBuf content = Unpooled.copiedBuffer(cause.message, CharsetUtil.UTF_8) - FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, INTERNAL_SERVER_ERROR, content) - response.headers().set(CONTENT_TYPE, "text/plain") - response.headers().set(CONTENT_LENGTH, content.readableBytes()) - ctx.write(response) - }, - channelReadComplete: { it.flush() } - ] as SimpleChannelInboundHandler) - } - ] as ChannelInitializer).channel(NioServerSocketChannel) - bootstrap.bind(port).sync() - - return eventLoopGroup - } - - @Override - void stopServer(EventLoopGroup server) { - server?.shutdownGracefully() - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "netty.request" - } - - @Override - boolean testException() { - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/807 - return false - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/okhttp-2.2.gradle b/instrumentation/okhttp/okhttp-2.2/okhttp-2.2.gradle deleted file mode 100644 index ac232a4aa0..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/okhttp-2.2.gradle +++ /dev/null @@ -1,22 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -/* -Note: The Interceptor class for OkHttp was not introduced until 2.2+, so we need to make sure the -instrumentation is not loaded unless the dependency is 2.2+. -*/ -muzzle { - pass { - group = "com.squareup.okhttp" - module = "okhttp" - versions = "[2.2,3)" - assertInverse = true - } -} - -dependencies { - library(group: 'com.squareup.okhttp', name: 'okhttp', version: '2.2.0') - - latestDepTestLibrary group: 'com.squareup.okhttp', name: 'okhttp', version: '[2.6,3)' -} - - diff --git a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2InstrumentationModule.java b/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2InstrumentationModule.java deleted file mode 100644 index f8aaae6def..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2InstrumentationModule.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v2_2; - -import static java.util.Collections.singletonList; -import static net.bytebuddy.matcher.ElementMatchers.isConstructor; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class OkHttp2InstrumentationModule extends InstrumentationModule { - public OkHttp2InstrumentationModule() { - super("okhttp", "okhttp-2.2"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new OkHttpClientInstrumentation()); - } - - public static class OkHttpClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("com.squareup.okhttp.OkHttpClient"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isConstructor(), OkHttp2InstrumentationModule.class.getName() + "$OkHttp2ClientAdvice"); - } - } - - public static class OkHttp2ClientAdvice { - @Advice.OnMethodExit - public static void addTracingInterceptor(@Advice.This OkHttpClient client) { - for (Interceptor interceptor : client.interceptors()) { - if (interceptor instanceof TracingInterceptor) { - return; - } - } - - client.interceptors().add(new TracingInterceptor()); - } - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttpClientTracer.java b/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttpClientTracer.java deleted file mode 100644 index 56738b9e21..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttpClientTracer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v2_2; - -import static io.opentelemetry.javaagent.instrumentation.okhttp.v2_2.RequestBuilderInjectAdapter.SETTER; - -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; - -public class OkHttpClientTracer extends HttpClientTracer { - private static final OkHttpClientTracer TRACER = new OkHttpClientTracer(); - - public static OkHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(Request request) { - return request.method(); - } - - @Override - protected URI url(Request request) throws URISyntaxException { - return request.url().toURI(); - } - - @Override - protected Integer status(Response response) { - return response.code(); - } - - @Override - protected String requestHeader(Request request, String name) { - return request.header(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.header(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.okhttp"; - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/RequestBuilderInjectAdapter.java b/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/RequestBuilderInjectAdapter.java deleted file mode 100644 index 8038c39687..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/RequestBuilderInjectAdapter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v2_2; - -import com.squareup.okhttp.Request; -import io.opentelemetry.context.propagation.TextMapPropagator; - -public class RequestBuilderInjectAdapter implements TextMapPropagator.Setter { - public static final RequestBuilderInjectAdapter SETTER = new RequestBuilderInjectAdapter(); - - @Override - public void set(Request.Builder carrier, String key, String value) { - carrier.addHeader(key, value); - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/TracingInterceptor.java b/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/TracingInterceptor.java deleted file mode 100644 index 8d263d4cdc..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/TracingInterceptor.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v2_2; - -import static io.opentelemetry.javaagent.instrumentation.okhttp.v2_2.OkHttpClientTracer.tracer; - -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.io.IOException; - -public class TracingInterceptor implements Interceptor { - @Override - public Response intercept(Chain chain) throws IOException { - Span span = tracer().startSpan(chain.request()); - Request.Builder requestBuilder = chain.request().newBuilder(); - - Response response; - try (Scope scope = tracer().startScope(span, requestBuilder)) { - response = chain.proceed(requestBuilder.build()); - } catch (Exception e) { - tracer().endExceptionally(span, e); - throw e; - } - tracer().end(span, response); - return response; - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/src/test/groovy/HeadersUtil.groovy b/instrumentation/okhttp/okhttp-2.2/src/test/groovy/HeadersUtil.groovy deleted file mode 100644 index 79c8745015..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/test/groovy/HeadersUtil.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class HeadersUtil { - static headersToArray(Map headers) { - String[] headersArr = new String[headers.size() * 2] - headers.eachWithIndex { k, v, i -> - headersArr[i] = k - headersArr[i + 1] = v - } - - headersArr - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/src/test/groovy/OkHttp2AsyncTest.groovy b/instrumentation/okhttp/okhttp-2.2/src/test/groovy/OkHttp2AsyncTest.groovy deleted file mode 100644 index cfebb192f1..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/test/groovy/OkHttp2AsyncTest.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static java.util.concurrent.TimeUnit.SECONDS - -import com.squareup.okhttp.Callback -import com.squareup.okhttp.Headers -import com.squareup.okhttp.MediaType -import com.squareup.okhttp.Request -import com.squareup.okhttp.RequestBody -import com.squareup.okhttp.Response -import com.squareup.okhttp.internal.http.HttpMethod -import java.util.concurrent.CountDownLatch -import java.util.concurrent.atomic.AtomicReference - -class OkHttp2AsyncTest extends OkHttp2Test { - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def body = HttpMethod.requiresRequestBody(method) ? RequestBody.create(MediaType.parse("text/plain"), "") : null - def request = new Request.Builder() - .url(uri.toURL()) - .method(method, body) - .headers(Headers.of(HeadersUtil.headersToArray(headers))) - .build() - - AtomicReference responseRef = new AtomicReference() - AtomicReference exRef = new AtomicReference() - def latch = new CountDownLatch(1) - - client.newCall(request).enqueue(new Callback() { - void onResponse(Response response) { - responseRef.set(response) - callback?.call() - latch.countDown() - } - - void onFailure(Request req, IOException e) { - exRef.set(e) - latch.countDown() - } - }) - latch.await(20, SECONDS) - if (exRef.get() != null) { - throw exRef.get() - } - return responseRef.get().code() - } -} diff --git a/instrumentation/okhttp/okhttp-2.2/src/test/groovy/OkHttp2Test.groovy b/instrumentation/okhttp/okhttp-2.2/src/test/groovy/OkHttp2Test.groovy deleted file mode 100644 index b15a9e7756..0000000000 --- a/instrumentation/okhttp/okhttp-2.2/src/test/groovy/OkHttp2Test.groovy +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import com.squareup.okhttp.Headers -import com.squareup.okhttp.MediaType -import com.squareup.okhttp.OkHttpClient -import com.squareup.okhttp.Request -import com.squareup.okhttp.RequestBody -import com.squareup.okhttp.internal.http.HttpMethod -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.TimeUnit -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class OkHttp2Test extends HttpClientTest { - @Shared - def client = new OkHttpClient() - - def setupSpec() { - client.setConnectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS) - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def body = HttpMethod.requiresRequestBody(method) ? RequestBody.create(MediaType.parse("text/plain"), "") : null - - def request = new Request.Builder() - .url(uri.toURL()) - .method(method, body) - .headers(Headers.of(HeadersUtil.headersToArray(headers))) - .build() - def response = client.newCall(request).execute() - callback?.call() - return response.code() - } - - boolean testRedirects() { - false - } -} diff --git a/instrumentation/okhttp/okhttp-3.0/okhttp-3.0.gradle b/instrumentation/okhttp/okhttp-3.0/okhttp-3.0.gradle deleted file mode 100644 index ea60c2918f..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/okhttp-3.0.gradle +++ /dev/null @@ -1,30 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.squareup.okhttp3" - module = "okhttp" - versions = "[3.0,)" - assertInverse = true - } -} - -/* -Note: there is a bit of dependency exclusion magic goin on. -We have to exclude all transitive dependencies on 'okhttp' because we would like to force -specific version. We cannot use . Unfortunately we cannot just force version on -a dependency because this doesn't work well with version ranges - it doesn't select latest. -And we cannot use configurations to exclude this dependency from everywhere in one go -because it looks like exclusions using configurations excludes dependency even if it explicit -not transitive. - */ -dependencies { - library(group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.0') - - testImplementation(project(':testing-common')) { - exclude module: 'okhttp' - } - - // 4.x.x-alpha has been released and it looks like there are lots of incompatible changes - latestDepTestLibrary group: 'com.squareup.okhttp3', name: 'okhttp', version: '[3.11.0, 4.0.0*)' -} diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3InstrumentationModule.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3InstrumentationModule.java deleted file mode 100644 index 1424cdb4b8..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3InstrumentationModule.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isConstructor; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; - -@AutoService(InstrumentationModule.class) -public class OkHttp3InstrumentationModule extends InstrumentationModule { - - public OkHttp3InstrumentationModule() { - super("okhttp", "okhttp-3.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new OkHttpClientInstrumentation()); - } - - public static class OkHttpClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("okhttp3.OkHttpClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isConstructor().and(takesArgument(0, named("okhttp3.OkHttpClient$Builder"))), - OkHttp3InstrumentationModule.class.getName() + "$OkHttp3Advice"); - } - } - - public static class OkHttp3Advice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void addTracingInterceptor(@Advice.Argument(0) OkHttpClient.Builder builder) { - for (Interceptor interceptor : builder.interceptors()) { - if (interceptor instanceof TracingInterceptor) { - return; - } - } - TracingInterceptor interceptor = new TracingInterceptor(); - builder.addInterceptor(interceptor); - } - } -} diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttpClientTracer.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttpClientTracer.java deleted file mode 100644 index 0e322c33c7..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttpClientTracer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0; - -import static io.opentelemetry.javaagent.instrumentation.okhttp.v3_0.RequestBuilderInjectAdapter.SETTER; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import okhttp3.Request; -import okhttp3.Response; - -public class OkHttpClientTracer extends HttpClientTracer { - private static final OkHttpClientTracer TRACER = new OkHttpClientTracer(); - - public static OkHttpClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(Request httpRequest) { - return httpRequest.method(); - } - - @Override - protected URI url(Request httpRequest) { - return httpRequest.url().uri(); - } - - @Override - protected Integer status(Response httpResponse) { - return httpResponse.code(); - } - - @Override - protected String requestHeader(Request request, String name) { - return request.header(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.header(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.okhttp"; - } -} diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/RequestBuilderInjectAdapter.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/RequestBuilderInjectAdapter.java deleted file mode 100644 index a0ff2bbd74..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/RequestBuilderInjectAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import okhttp3.Request; - -/** - * Helper class to inject span context into request headers. - * - * @author Pavol Loffay - */ -public class RequestBuilderInjectAdapter implements TextMapPropagator.Setter { - - public static final RequestBuilderInjectAdapter SETTER = new RequestBuilderInjectAdapter(); - - @Override - public void set(Request.Builder carrier, String key, String value) { - carrier.addHeader(key, value); - } -} diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/TracingInterceptor.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/TracingInterceptor.java deleted file mode 100644 index 24887c40fe..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/TracingInterceptor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0; - -import static io.opentelemetry.javaagent.instrumentation.okhttp.v3_0.OkHttpClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.io.IOException; -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; - -public class TracingInterceptor implements Interceptor { - - @Override - public Response intercept(Chain chain) throws IOException { - Span span = tracer().startSpan(chain.request()); - - Response response; - Request.Builder requestBuilder = chain.request().newBuilder(); - try (Scope ignored = tracer().startScope(span, requestBuilder)) { - response = chain.proceed(requestBuilder.build()); - } catch (Exception e) { - tracer().endExceptionally(span, e); - throw e; - } - tracer().end(span, response); - return response; - } -} diff --git a/instrumentation/okhttp/okhttp-3.0/src/test/groovy/OkHttp3AsyncTest.groovy b/instrumentation/okhttp/okhttp-3.0/src/test/groovy/OkHttp3AsyncTest.groovy deleted file mode 100644 index 7fb437f881..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/src/test/groovy/OkHttp3AsyncTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static java.util.concurrent.TimeUnit.SECONDS - -import java.util.concurrent.CountDownLatch -import java.util.concurrent.atomic.AtomicReference -import okhttp3.Call -import okhttp3.Callback -import okhttp3.Headers -import okhttp3.MediaType -import okhttp3.Request -import okhttp3.RequestBody -import okhttp3.Response -import okhttp3.internal.http.HttpMethod - -class OkHttp3AsyncTest extends OkHttp3Test { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def body = HttpMethod.requiresRequestBody(method) ? RequestBody.create(MediaType.parse("text/plain"), "") : null - def request = new Request.Builder() - .url(uri.toURL()) - .method(method, body) - .headers(Headers.of(headers)) - .build() - - AtomicReference responseRef = new AtomicReference() - AtomicReference exRef = new AtomicReference() - def latch = new CountDownLatch(1) - - client.newCall(request).enqueue(new Callback() { - void onResponse(Call call, Response response) { - responseRef.set(response) - callback?.call() - latch.countDown() - } - - void onFailure(Call call, IOException e) { - exRef.set(e) - latch.countDown() - } - }) - latch.await(20, SECONDS) - if (exRef.get() != null) { - throw exRef.get() - } - return responseRef.get().code() - } -} diff --git a/instrumentation/okhttp/okhttp-3.0/src/test/groovy/OkHttp3Test.groovy b/instrumentation/okhttp/okhttp-3.0/src/test/groovy/OkHttp3Test.groovy deleted file mode 100644 index f691e90b45..0000000000 --- a/instrumentation/okhttp/okhttp-3.0/src/test/groovy/OkHttp3Test.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.TimeUnit -import okhttp3.Headers -import okhttp3.MediaType -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.RequestBody -import okhttp3.internal.http.HttpMethod -import spock.lang.Timeout - -@Timeout(5) -class OkHttp3Test extends HttpClientTest { - - def client = new OkHttpClient.Builder() - .connectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS) - .build() - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def body = HttpMethod.requiresRequestBody(method) ? RequestBody.create(MediaType.parse("text/plain"), "") : null - def request = new Request.Builder() - .url(uri.toURL()) - .method(method, body) - .headers(Headers.of(headers)).build() - def response = client.newCall(request).execute() - callback?.call() - return response.code() - } - - boolean testRedirects() { - false - } -} diff --git a/instrumentation/opentelemetry-annotations-1.0/opentelemetry-annotations-1.0.gradle b/instrumentation/opentelemetry-annotations-1.0/opentelemetry-annotations-1.0.gradle deleted file mode 100644 index ccb966a18f..0000000000 --- a/instrumentation/opentelemetry-annotations-1.0/opentelemetry-annotations-1.0.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - // this instrumentation needs to do similar shading dance as opentelemetry-api-1.0 because - // the @WithSpan annotation references the OpenTelemetry API's Span.Kind class - // - // see the comment in opentelemetry-api-1.0.gradle for more details - compileOnly project(path: ':opentelemetry-ext-annotations-shaded-for-instrumenting', configuration: 'shadow') - - testImplementation project(path: ':opentelemetry-ext-annotations-shaded-for-instrumenting', configuration: 'shadow') -} diff --git a/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanAdvice.java b/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanAdvice.java deleted file mode 100644 index b7cdffff4e..0000000000 --- a/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanAdvice.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.otelannotations; - -import static io.opentelemetry.javaagent.instrumentation.otelannotations.WithSpanTracer.tracer; - -import application.io.opentelemetry.extension.annotations.WithSpan; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.lang.reflect.Method; -import net.bytebuddy.asm.Advice; - -/** - * Instrumentation for methods annotated with {@link WithSpan} annotation. - * - * @see WithSpanInstrumentationModule - */ -public class WithSpanAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Origin Method method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - WithSpan applicationAnnotation = method.getAnnotation(WithSpan.class); - - span = - tracer() - .startSpan( - tracer().spanNameForMethodWithAnnotation(applicationAnnotation, method), - tracer().extractSpanKind(applicationAnnotation)); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } -} diff --git a/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanInstrumentationModule.java b/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanInstrumentationModule.java deleted file mode 100644 index a242efbfbc..0000000000 --- a/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanInstrumentationModule.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.otelannotations; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.none; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import application.io.opentelemetry.extension.annotations.WithSpan; -import com.google.auto.service.AutoService; -import io.opentelemetry.instrumentation.api.config.Config; -import io.opentelemetry.instrumentation.api.config.MethodsConfigurationParser; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import java.util.Set; -import net.bytebuddy.description.ByteCodeElement; -import net.bytebuddy.description.annotation.AnnotationSource; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; - -/** Instrumentation for methods annotated with {@link WithSpan} annotation. */ -@AutoService(InstrumentationModule.class) -public class WithSpanInstrumentationModule extends InstrumentationModule { - - private static final String TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG = - "otel.instrumentation.opentelemetry-annotations.exclude-methods"; - - public WithSpanInstrumentationModule() { - super("opentelemetry-annotations"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AnnotatedMethodInstrumentation()); - } - - public static class AnnotatedMethodInstrumentation implements TypeInstrumentation { - private final ElementMatcher.Junction annotatedMethodMatcher; - // this matcher matches all methods that should be excluded from transformation - private final ElementMatcher.Junction excludedMethodsMatcher; - - AnnotatedMethodInstrumentation() { - annotatedMethodMatcher = - isAnnotatedWith(named("application.io.opentelemetry.extension.annotations.WithSpan")); - excludedMethodsMatcher = configureExcludedMethods(); - } - - @Override - public ElementMatcher typeMatcher() { - return declaresMethod(annotatedMethodMatcher); - } - - @Override - public Map, String> transformers() { - return singletonMap( - annotatedMethodMatcher.and(not(excludedMethodsMatcher)), WithSpanAdvice.class.getName()); - } - - /* - Returns a matcher for all methods that should be excluded from auto-instrumentation by - annotation-based advices. - */ - static ElementMatcher.Junction configureExcludedMethods() { - ElementMatcher.Junction result = none(); - - Map> excludedMethods = - MethodsConfigurationParser.parse( - Config.get().getProperty(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); - for (Map.Entry> entry : excludedMethods.entrySet()) { - String className = entry.getKey(); - ElementMatcher.Junction classMather = - isDeclaredBy(ElementMatchers.named(className)); - - ElementMatcher.Junction excludedMethodsMatcher = none(); - for (String methodName : entry.getValue()) { - excludedMethodsMatcher = excludedMethodsMatcher.or(ElementMatchers.named(methodName)); - } - - result = result.or(classMather.and(excludedMethodsMatcher)); - } - - return result; - } - } -} diff --git a/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanTracer.java b/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanTracer.java deleted file mode 100644 index c460efc0c5..0000000000 --- a/instrumentation/opentelemetry-annotations-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/otelannotations/WithSpanTracer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.otelannotations; - -import application.io.opentelemetry.api.trace.Span; -import application.io.opentelemetry.extension.annotations.WithSpan; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.lang.reflect.Method; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class WithSpanTracer extends BaseTracer { - private static final WithSpanTracer TRACER = new WithSpanTracer(); - - public static WithSpanTracer tracer() { - return TRACER; - } - - private static final Logger log = LoggerFactory.getLogger(WithSpanTracer.class); - - /** - * This method is used to generate an acceptable span (operation) name based on a given method - * reference. It first checks for existence of {@link WithSpan} annotation. If it is present, then - * tries to derive name from its {@code value} attribute. Otherwise delegates to {@link - * #spanNameForMethod(Method)}. - */ - public String spanNameForMethodWithAnnotation(WithSpan applicationAnnotation, Method method) { - if (applicationAnnotation != null && !applicationAnnotation.value().isEmpty()) { - return applicationAnnotation.value(); - } - return spanNameForMethod(method); - } - - public Kind extractSpanKind(WithSpan applicationAnnotation) { - Span.Kind applicationKind = - applicationAnnotation != null ? applicationAnnotation.kind() : Span.Kind.INTERNAL; - return toAgentOrNull(applicationKind); - } - - public static Kind toAgentOrNull(Span.Kind applicationSpanKind) { - try { - return Kind.valueOf(applicationSpanKind.name()); - } catch (IllegalArgumentException e) { - log.debug("unexpected span kind: {}", applicationSpanKind.name()); - return Kind.INTERNAL; - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.opentelemetry-annotations"; - } -} diff --git a/instrumentation/opentelemetry-annotations-1.0/src/test/groovy/WithSpanInstrumentationTest.groovy b/instrumentation/opentelemetry-annotations-1.0/src/test/groovy/WithSpanInstrumentationTest.groovy deleted file mode 100644 index b4d568e794..0000000000 --- a/instrumentation/opentelemetry-annotations-1.0/src/test/groovy/WithSpanInstrumentationTest.groovy +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.ConfigUtils -import io.opentelemetry.test.annotation.TracedWithSpan - -/** - * This test verifies that auto instrumentation supports {@link io.opentelemetry.extension.annotations.WithSpan} contrib annotation. - */ -class WithSpanInstrumentationTest extends AgentTestRunner { - static final PREVIOUS_CONFIG = ConfigUtils.updateConfigAndResetInstrumentation { - it.setProperty("otel.instrumentation.opentelemetry-annotations.exclude-methods", - "${TracedWithSpan.name}[ignored]") - } - - def cleanupSpec() { - ConfigUtils.setConfig(PREVIOUS_CONFIG) - } - - def "should derive automatic name"() { - setup: - new TracedWithSpan().otel() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.otel" - kind Span.Kind.INTERNAL - hasNoParent() - errored false - attributes { - } - } - } - } - } - - def "should take span name from annotation"() { - setup: - new TracedWithSpan().namedOtel() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "manualName" - hasNoParent() - errored false - attributes { - } - } - } - } - } - - def "should take span kind from annotation"() { - setup: - new TracedWithSpan().oneOfAKind() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.oneOfAKind" - kind Span.Kind.PRODUCER - hasNoParent() - errored false - attributes { - } - } - } - } - } - - - def "should ignore method excluded by trace.annotated.methods.exclude configuration"() { - setup: - new TracedWithSpan().ignored() - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - } -} diff --git a/instrumentation/opentelemetry-annotations-1.0/src/test/java/io/opentelemetry/test/annotation/TracedWithSpan.java b/instrumentation/opentelemetry-annotations-1.0/src/test/java/io/opentelemetry/test/annotation/TracedWithSpan.java deleted file mode 100644 index 572245f1e0..0000000000 --- a/instrumentation/opentelemetry-annotations-1.0/src/test/java/io/opentelemetry/test/annotation/TracedWithSpan.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.test.annotation; - -import application.io.opentelemetry.api.trace.Span.Kind; -import application.io.opentelemetry.extension.annotations.WithSpan; - -public class TracedWithSpan { - - @WithSpan - public String otel() { - return "hello!"; - } - - @WithSpan("manualName") - public String namedOtel() { - return "hello!"; - } - - @WithSpan - public String ignored() { - return "hello!"; - } - - @WithSpan(kind = Kind.PRODUCER) - public String oneOfAKind() { - return "hello!"; - } -} diff --git a/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy b/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy index 15d403540e..1b169368bd 100644 --- a/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy +++ b/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy @@ -4,9 +4,9 @@ */ import application.io.opentelemetry.api.OpenTelemetry +import application.io.opentelemetry.api.trace.Span import application.io.opentelemetry.context.Context import application.io.opentelemetry.context.ContextKey -import application.io.opentelemetry.api.trace.Span import io.opentelemetry.instrumentation.test.AgentTestRunner import java.util.concurrent.atomic.AtomicReference diff --git a/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextTest.groovy b/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextTest.groovy index 20e2e31283..7e2c8fe83b 100644 --- a/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextTest.groovy +++ b/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextTest.groovy @@ -4,8 +4,8 @@ */ import application.io.opentelemetry.api.OpenTelemetry -import application.io.opentelemetry.context.Context import application.io.opentelemetry.api.trace.Span +import application.io.opentelemetry.context.Context import io.opentelemetry.instrumentation.test.AgentTestRunner class ContextTest extends AgentTestRunner { diff --git a/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/TracerTest.groovy b/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/TracerTest.groovy index 7c85f51f37..3a22b739df 100644 --- a/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/TracerTest.groovy +++ b/instrumentation/opentelemetry-api-1.0/javaagent/src/test/groovy/TracerTest.groovy @@ -4,14 +4,15 @@ */ import static application.io.opentelemetry.api.trace.Span.Kind.PRODUCER + import application.io.opentelemetry.api.OpenTelemetry import application.io.opentelemetry.api.common.Attributes -import application.io.opentelemetry.context.Context -import application.io.opentelemetry.context.Scope import application.io.opentelemetry.api.trace.Span import application.io.opentelemetry.api.trace.StatusCode -import io.opentelemetry.instrumentation.test.AgentTestRunner +import application.io.opentelemetry.context.Context +import application.io.opentelemetry.context.Scope import io.opentelemetry.api.trace.attributes.SemanticAttributes +import io.opentelemetry.instrumentation.test.AgentTestRunner class TracerTest extends AgentTestRunner { diff --git a/instrumentation/opentelemetry-api-1.0/opentelemetry-api-1.0.gradle b/instrumentation/opentelemetry-api-1.0/opentelemetry-api-1.0.gradle deleted file mode 100644 index 98ae9c0197..0000000000 --- a/instrumentation/opentelemetry-api-1.0/opentelemetry-api-1.0.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -dependencies { - // this instrumentation needs to be able to reference both the OpenTelemetry API - // that is shaded in the bootstrap class loader (for sending telemetry to the agent), - // and the OpenTelemetry API that the user brings (in order to capture that telemetry) - // - // since (all) instrumentation already uses OpenTelemetry API for sending telemetry to the agent, - // this instrumentation uses a "temporarily shaded" OpenTelemetry API to represent the - // OpenTelemetry API that the user brings - // - // then later, after the OpenTelemetry API in the bootstrap class loader is shaded, - // the "temporarily shaded" OpenTelemetry API is unshaded, so that it will apply to the - // OpenTelemetry API that the user brings - // - // so in the code "application.io.opentelemetry.*" refers to the (unshaded) OpenTelemetry API that - // the application brings (as those references will be translated during the build to remove the - // "application." prefix) - // - // and in the code "io.opentelemetry.*" refers to the (shaded) OpenTelemetry API that is used by - // the agent (as those references will later be shaded) - compileOnly project(path: ':opentelemetry-api-shaded-for-instrumenting', configuration: 'shadow') - - // using OpenTelemetry SDK to make sure that instrumentation doesn't cause - // OpenTelemetrySdk.getTracerProvider() to throw ClassCastException - testImplementation project(path: ':opentelemetry-sdk-shaded-for-instrumenting', configuration: 'shadow') -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/BaggageUtilsInstrumentation.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/BaggageUtilsInstrumentation.java deleted file mode 100644 index 99f5b94018..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/BaggageUtilsInstrumentation.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import application.io.opentelemetry.context.Context; -import io.opentelemetry.api.baggage.Baggage; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -// TODO: Actually bridge correlation context. We currently just stub out withBaggage -// to have minimum functionality with SDK shim implementations. -// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/973 -public class BaggageUtilsInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("application.io.opentelemetry.api.baggage.BaggageUtils"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(isPublic()).and(isStatic()).and(named("withBaggage")).and(takesArguments(2)), - BaggageUtilsInstrumentation.class.getName() + "$WithBaggageAdvice"); - return transformers; - } - - public static class WithBaggageAdvice { - - @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) - public static Object onEnter() { - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Argument(0) Baggage applicationBaggage, - @Advice.Argument(1) Context applicationContext, - @Advice.Return(readOnly = false) Context applicationUpdatedContext) { - applicationUpdatedContext = applicationContext; - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/ContextInstrumentation.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/ContextInstrumentation.java deleted file mode 100644 index 5d6db351fc..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/ContextInstrumentation.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import application.io.opentelemetry.context.Context; -import application.io.opentelemetry.context.ContextStorage; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * Returns {@link AgentContextStorage} as the implementation of {@link ContextStorage} in the - * application classpath. We do this instead of using the normal service loader mechanism to make - * sure there is no dependency on a system property or possibility of a user overriding this since - * it's required for instrumentation in the agent to work properly. - */ -public class ContextInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("application.io.opentelemetry.context.DefaultContext"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isMethod().and(isStatic()).and(named("root")), - ContextInstrumentation.class.getName() + "$GetAdvice"); - } - - public static class GetAdvice { - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit(@Advice.Return(readOnly = false) Context root) { - root = - new AgentContextStorage.AgentContextWrapper( - io.opentelemetry.context.Context.root(), root); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/ContextStorageInstrumentation.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/ContextStorageInstrumentation.java deleted file mode 100644 index 671659012c..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/ContextStorageInstrumentation.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import application.io.opentelemetry.context.ContextStorage; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * Returns {@link AgentContextStorage} as the implementation of {@link ContextStorage} in the - * application classpath. We do this instead of using the normal service loader mechanism to make - * sure there is no dependency on a system property or possibility of a user overriding this since - * it's required for instrumentation in the agent to work properly. - */ -public class ContextStorageInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("application.io.opentelemetry.context.LazyStorage"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isMethod().and(isStatic()).and(named("get")), - ContextStorageInstrumentation.class.getName() + "$GetAdvice"); - } - - public static class GetAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) - public static Object onEnter() { - return null; - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit(@Advice.Return(readOnly = false) ContextStorage storage) { - storage = AgentContextStorage.INSTANCE; - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/LabelBridging.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/LabelBridging.java deleted file mode 100644 index 8585359489..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/LabelBridging.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import io.opentelemetry.api.common.Labels; -import io.opentelemetry.api.common.LabelsBuilder; - -/** - * This class converts between Labels class that application brings and Labels class that agent - * uses. - * - *

TODO probably not the most performant solution... - */ -public class LabelBridging { - - public static Labels toAgent(application.io.opentelemetry.api.common.Labels applicationLabels) { - LabelsBuilder builder = Labels.builder(); - applicationLabels.forEach(builder::put); - return builder.build(); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java deleted file mode 100644 index 737367bddb..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class OpenTelemetryApiInstrumentationModule extends InstrumentationModule { - public OpenTelemetryApiInstrumentationModule() { - super("opentelemetry-api"); - } - - @Override - public List typeInstrumentations() { - return asList( - new BaggageUtilsInstrumentation(), - new ContextInstrumentation(), - new ContextStorageInstrumentation(), - new OpenTelemetryInstrumentation(), - new SpanInstrumentation()); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryInstrumentation.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryInstrumentation.java deleted file mode 100644 index 99040d099b..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryInstrumentation.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import application.io.opentelemetry.api.metrics.MeterProvider; -import application.io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.propagation.ApplicationContextPropagators; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics.ApplicationMeterProvider; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.ApplicationTracerProvider; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.HashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class OpenTelemetryInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("application.io.opentelemetry.api.OpenTelemetry"); - } - - @Override - public Map, String> transformers() { - Map, String> transformers = new HashMap<>(); - transformers.put( - isMethod().and(isPublic()).and(named("getGlobalTracerProvider")).and(takesArguments(0)), - OpenTelemetryInstrumentation.class.getName() + "$GetTracerProviderAdvice"); - transformers.put( - isMethod().and(isPublic()).and(named("getGlobalMeterProvider")).and(takesArguments(0)), - OpenTelemetryInstrumentation.class.getName() + "$GetMeterProviderAdvice"); - transformers.put( - isMethod().and(isPublic()).and(named("getGlobalPropagators")).and(takesArguments(0)), - OpenTelemetryInstrumentation.class.getName() + "$GetPropagatorsAdvice"); - return transformers; - } - - public static class GetTracerProviderAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return(readOnly = false) - application.io.opentelemetry.api.trace.TracerProvider applicationTracerProvider) { - applicationTracerProvider = new ApplicationTracerProvider(applicationTracerProvider); - } - } - - public static class GetMeterProviderAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return(readOnly = false) MeterProvider applicationMeterProvider) { - applicationMeterProvider = new ApplicationMeterProvider(); - } - } - - public static class GetPropagatorsAdvice { - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Return(readOnly = false) ContextPropagators applicationContextPropagators) { - applicationContextPropagators = new ApplicationContextPropagators(); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/SpanInstrumentation.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/SpanInstrumentation.java deleted file mode 100644 index da9aa48388..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/SpanInstrumentation.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; - -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import application.io.opentelemetry.api.trace.Span; -import application.io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class SpanInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("application.io.opentelemetry.api.trace.PropagatedSpan"); - } - - @Override - public Map, String> transformers() { - return Collections.singletonMap( - isMethod().and(isStatic()).and(named("create")), - SpanInstrumentation.class.getName() + "$CreateAdvice"); - } - - public static class CreateAdvice { - // We replace the return value completely so don't need to call the method. - @Advice.OnMethodEnter(skipOn = Advice.OnDefaultValue.class) - public static boolean methodEnter() { - return false; - } - - @Advice.OnMethodExit - public static void methodExit( - @Advice.Argument(0) SpanContext applicationSpanContext, - @Advice.Return(readOnly = false) Span applicationSpan) { - applicationSpan = - Bridging.toApplication( - io.opentelemetry.api.trace.Span.wrap(Bridging.toAgent(applicationSpanContext))); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/AgentContextStorage.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/AgentContextStorage.java deleted file mode 100644 index 58dcd8d37a..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/AgentContextStorage.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context; - -import application.io.opentelemetry.api.trace.Span; -import application.io.opentelemetry.context.Context; -import application.io.opentelemetry.context.ContextKey; -import application.io.opentelemetry.context.ContextStorage; -import application.io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; -import java.lang.reflect.Field; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * {@link ContextStorage} which stores the {@link Context} in the user's application inside the - * {@link Context} in the agent. This allows for context interaction to be maintained between the - * app and agent. - * - *

This storage allows for implicit parenting of context to exist between the agent and - * application by storing the concrete application context in the agent context and returning a - * wrapper which accesses into this stored concrete context. - * - *

This storage also makes sure that OpenTelemetry objects are shared within the context. To do - * this, it recognizes the keys for OpenTelemetry objects (e.g, {@link Span}, Baggage (WIP)) and - * always stores and retrieves them from the agent context, even when accessed from the application. - * All other accesses are to the concrete application context. - */ -public class AgentContextStorage implements ContextStorage { - - private static final Logger logger = LoggerFactory.getLogger(AgentContextStorage.class); - - public static final AgentContextStorage INSTANCE = new AgentContextStorage(); - - public static io.opentelemetry.context.Context getAgentContext(Context applicationContext) { - if (applicationContext instanceof AgentContextWrapper) { - return ((AgentContextWrapper) applicationContext).toAgentContext(); - } - if (logger.isDebugEnabled()) { - logger.debug( - "unexpected context: {}", applicationContext, new Exception("unexpected context")); - } - return io.opentelemetry.context.Context.root(); - } - - static final io.opentelemetry.context.ContextKey APPLICATION_CONTEXT = - io.opentelemetry.context.ContextKey.named("otel-context"); - - static final io.opentelemetry.context.ContextKey - AGENT_SPAN_CONTEXT_KEY; - static final ContextKey APPLICATION_SPAN_CONTEXT_KEY; - - static { - io.opentelemetry.context.ContextKey agentSpanContextKey; - try { - Class tracingContextUtils = Class.forName("io.opentelemetry.api.trace.SpanContextKey"); - Field contextSpanKeyField = tracingContextUtils.getDeclaredField("KEY"); - contextSpanKeyField.setAccessible(true); - agentSpanContextKey = - (io.opentelemetry.context.ContextKey) - contextSpanKeyField.get(null); - } catch (Throwable t) { - agentSpanContextKey = null; - } - AGENT_SPAN_CONTEXT_KEY = agentSpanContextKey; - - ContextKey applicationSpanContextKey; - try { - Class tracingContextUtils = - Class.forName("application.io.opentelemetry.api.trace.SpanContextKey"); - Field contextSpanKeyField = tracingContextUtils.getDeclaredField("KEY"); - contextSpanKeyField.setAccessible(true); - applicationSpanContextKey = (ContextKey) contextSpanKeyField.get(null); - } catch (Throwable t) { - applicationSpanContextKey = null; - } - APPLICATION_SPAN_CONTEXT_KEY = applicationSpanContextKey; - } - - @Override - public Scope attach(Context toAttach) { - io.opentelemetry.context.Context currentAgentContext = - io.opentelemetry.context.Context.current(); - Context currentApplicationContext = currentAgentContext.get(APPLICATION_CONTEXT); - if (currentApplicationContext == null) { - currentApplicationContext = Context.root(); - } - - if (currentApplicationContext == toAttach) { - return Scope.noop(); - } - - io.opentelemetry.context.Context newAgentContext; - if (toAttach instanceof AgentContextWrapper) { - newAgentContext = ((AgentContextWrapper) toAttach).toAgentContext(); - } else { - newAgentContext = currentAgentContext.with(APPLICATION_CONTEXT, toAttach); - } - - return newAgentContext.makeCurrent()::close; - } - - @Override - public Context current() { - io.opentelemetry.context.Context agentContext = io.opentelemetry.context.Context.current(); - Context applicationContext = agentContext.get(APPLICATION_CONTEXT); - if (applicationContext == null) { - applicationContext = Context.root(); - } - return new AgentContextWrapper(io.opentelemetry.context.Context.current(), applicationContext); - } - - public static class AgentContextWrapper implements Context { - private final io.opentelemetry.context.Context agentContext; - private final Context applicationContext; - - public AgentContextWrapper( - io.opentelemetry.context.Context agentContext, Context applicationContext) { - this.agentContext = agentContext; - this.applicationContext = applicationContext; - } - - io.opentelemetry.context.Context toAgentContext() { - if (agentContext.get(APPLICATION_CONTEXT) == applicationContext) { - return agentContext; - } - return agentContext.with(APPLICATION_CONTEXT, applicationContext); - } - - @Override - public V get(ContextKey key) { - if (key == APPLICATION_SPAN_CONTEXT_KEY) { - io.opentelemetry.api.trace.Span agentSpan = agentContext.get(AGENT_SPAN_CONTEXT_KEY); - if (agentSpan == null) { - return null; - } - Span applicationSpan = Bridging.toApplication(agentSpan); - @SuppressWarnings("unchecked") - V value = (V) applicationSpan; - return value; - } - return applicationContext.get(key); - } - - @Override - public Context with(ContextKey k1, V v1) { - if (k1 == APPLICATION_SPAN_CONTEXT_KEY) { - Span applicationSpan = (Span) v1; - io.opentelemetry.api.trace.Span agentSpan = Bridging.toAgentOrNull(applicationSpan); - if (agentSpan == null) { - return this; - } - return new AgentContextWrapper( - agentContext.with(AGENT_SPAN_CONTEXT_KEY, agentSpan), applicationContext); - } - return new AgentContextWrapper(agentContext, applicationContext.with(k1, v1)); - } - } - - static class SpanContextKeys {} -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/propagation/ApplicationContextPropagators.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/propagation/ApplicationContextPropagators.java deleted file mode 100644 index 10467d483a..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/propagation/ApplicationContextPropagators.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.propagation; - -import application.io.opentelemetry.context.propagation.ContextPropagators; -import application.io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.api.OpenTelemetry; - -public class ApplicationContextPropagators implements ContextPropagators { - - private final ApplicationTextMapPropagator applicationTextMapPropagator; - - public ApplicationContextPropagators() { - applicationTextMapPropagator = - new ApplicationTextMapPropagator( - OpenTelemetry.getGlobalPropagators().getTextMapPropagator()); - } - - @Override - public TextMapPropagator getTextMapPropagator() { - return applicationTextMapPropagator; - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/propagation/ApplicationTextMapPropagator.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/propagation/ApplicationTextMapPropagator.java deleted file mode 100644 index 758d834121..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/propagation/ApplicationTextMapPropagator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.propagation; - -import application.io.opentelemetry.context.Context; -import application.io.opentelemetry.context.propagation.TextMapPropagator; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; -import java.util.List; - -class ApplicationTextMapPropagator implements TextMapPropagator { - - private final io.opentelemetry.context.propagation.TextMapPropagator agentTextMapPropagator; - - ApplicationTextMapPropagator( - io.opentelemetry.context.propagation.TextMapPropagator agentTextMapPropagator) { - this.agentTextMapPropagator = agentTextMapPropagator; - } - - @Override - public List fields() { - return agentTextMapPropagator.fields(); - } - - @Override - public Context extract( - Context applicationContext, C carrier, TextMapPropagator.Getter applicationGetter) { - io.opentelemetry.context.Context agentContext = - AgentContextStorage.getAgentContext(applicationContext); - io.opentelemetry.context.Context agentUpdatedContext = - agentTextMapPropagator.extract(agentContext, carrier, new AgentGetter<>(applicationGetter)); - if (agentUpdatedContext == agentContext) { - return applicationContext; - } - return new AgentContextStorage.AgentContextWrapper(agentUpdatedContext, applicationContext); - } - - @Override - public void inject( - Context applicationContext, C carrier, TextMapPropagator.Setter applicationSetter) { - io.opentelemetry.context.Context agentContext = - AgentContextStorage.getAgentContext(applicationContext); - agentTextMapPropagator.inject(agentContext, carrier, new AgentSetter<>(applicationSetter)); - } - - private static class AgentGetter - implements io.opentelemetry.context.propagation.TextMapPropagator.Getter { - - private final TextMapPropagator.Getter applicationGetter; - - AgentGetter(TextMapPropagator.Getter applicationGetter) { - this.applicationGetter = applicationGetter; - } - - @Override - public Iterable keys(C c) { - return applicationGetter.keys(c); - } - - @Override - public String get(C carrier, String key) { - return applicationGetter.get(carrier, key); - } - } - - private static class AgentSetter - implements io.opentelemetry.context.propagation.TextMapPropagator.Setter { - - private final TextMapPropagator.Setter applicationSetter; - - AgentSetter(Setter applicationSetter) { - this.applicationSetter = applicationSetter; - } - - @Override - public void set(C carrier, String key, String value) { - applicationSetter.set(carrier, key, value); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationBatchRecorder.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationBatchRecorder.java deleted file mode 100644 index d2276d673a..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationBatchRecorder.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.metrics.BatchRecorder; -import application.io.opentelemetry.api.metrics.DoubleCounter; -import application.io.opentelemetry.api.metrics.DoubleUpDownCounter; -import application.io.opentelemetry.api.metrics.DoubleValueRecorder; -import application.io.opentelemetry.api.metrics.LongCounter; -import application.io.opentelemetry.api.metrics.LongUpDownCounter; -import application.io.opentelemetry.api.metrics.LongValueRecorder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class ApplicationBatchRecorder implements BatchRecorder { - - private static final Logger log = LoggerFactory.getLogger(ApplicationBatchRecorder.class); - - private final io.opentelemetry.api.metrics.BatchRecorder agentBatchRecorder; - - ApplicationBatchRecorder(io.opentelemetry.api.metrics.BatchRecorder agentBatchRecorder) { - this.agentBatchRecorder = agentBatchRecorder; - } - - @Override - public BatchRecorder put(LongValueRecorder measure, long value) { - if (measure instanceof ApplicationLongValueRecorder) { - agentBatchRecorder.put( - ((ApplicationLongValueRecorder) measure).getAgentLongValueRecorder(), value); - } else { - log.debug("unexpected measure: {}", measure); - } - return this; - } - - @Override - public BatchRecorder put(DoubleValueRecorder measure, double value) { - if (measure instanceof ApplicationDoubleValueRecorder) { - agentBatchRecorder.put( - ((ApplicationDoubleValueRecorder) measure).getAgentDoubleValueRecorder(), value); - } else { - log.debug("unexpected measure: {}", measure); - } - return this; - } - - @Override - public BatchRecorder put(LongCounter counter, long value) { - if (counter instanceof ApplicationLongCounter) { - agentBatchRecorder.put(((ApplicationLongCounter) counter).getAgentLongCounter(), value); - } else { - log.debug("unexpected counter: {}", counter); - } - return this; - } - - @Override - public BatchRecorder put(DoubleCounter counter, double value) { - if (counter instanceof ApplicationDoubleCounter) { - agentBatchRecorder.put(((ApplicationDoubleCounter) counter).getAgentDoubleCounter(), value); - } else { - log.debug("unexpected counter: {}", counter); - } - return this; - } - - @Override - public BatchRecorder put(LongUpDownCounter counter, long value) { - if (counter instanceof ApplicationLongUpDownCounter) { - agentBatchRecorder.put( - ((ApplicationLongUpDownCounter) counter).getAgentLongUpDownCounter(), value); - } else { - log.debug("unexpected counter: {}", counter); - } - return this; - } - - @Override - public BatchRecorder put(DoubleUpDownCounter counter, double value) { - if (counter instanceof ApplicationDoubleUpDownCounter) { - agentBatchRecorder.put( - ((ApplicationDoubleUpDownCounter) counter).getAgentDoubleUpDownCounter(), value); - } else { - log.debug("unexpected counter: {}", counter); - } - return this; - } - - @Override - public void record() { - agentBatchRecorder.record(); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleCounter.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleCounter.java deleted file mode 100644 index a1c99dad51..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleCounter.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.DoubleCounter; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationDoubleCounter implements DoubleCounter { - - private final io.opentelemetry.api.metrics.DoubleCounter agentDoubleCounter; - - ApplicationDoubleCounter(io.opentelemetry.api.metrics.DoubleCounter agentDoubleCounter) { - this.agentDoubleCounter = agentDoubleCounter; - } - - io.opentelemetry.api.metrics.DoubleCounter getAgentDoubleCounter() { - return agentDoubleCounter; - } - - @Override - public void add(double delta, Labels labels) { - agentDoubleCounter.add(delta, LabelBridging.toAgent(labels)); - } - - @Override - public void add(double v) { - agentDoubleCounter.add(v); - } - - @Override - public BoundDoubleCounter bind(Labels labels) { - return new BoundInstrument(agentDoubleCounter.bind(LabelBridging.toAgent(labels))); - } - - static class BoundInstrument implements DoubleCounter.BoundDoubleCounter { - - private final io.opentelemetry.api.metrics.DoubleCounter.BoundDoubleCounter - agentBoundDoubleCounter; - - BoundInstrument( - io.opentelemetry.api.metrics.DoubleCounter.BoundDoubleCounter agentBoundDoubleCounter) { - this.agentBoundDoubleCounter = agentBoundDoubleCounter; - } - - @Override - public void add(double delta) { - agentBoundDoubleCounter.add(delta); - } - - @Override - public void unbind() { - agentBoundDoubleCounter.unbind(); - } - } - - static class Builder implements DoubleCounter.Builder { - - private final io.opentelemetry.api.metrics.DoubleCounter.Builder agentBuilder; - - Builder(io.opentelemetry.api.metrics.DoubleCounter.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public DoubleCounter.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public DoubleCounter.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public DoubleCounter build() { - return new ApplicationDoubleCounter(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleSumObserver.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleSumObserver.java deleted file mode 100644 index 779804a509..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleSumObserver.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.DoubleSumObserver; -import io.opentelemetry.api.metrics.AsynchronousInstrument; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationDoubleSumObserver implements DoubleSumObserver { - - private final io.opentelemetry.api.metrics.DoubleSumObserver agentDoubleSumObserver; - - protected ApplicationDoubleSumObserver( - io.opentelemetry.api.metrics.DoubleSumObserver agentDoubleSumObserver) { - this.agentDoubleSumObserver = agentDoubleSumObserver; - } - - @Override - public void setCallback(Callback metricUpdater) { - agentDoubleSumObserver.setCallback(new AgentResultDoubleSumObserver(metricUpdater)); - } - - static class AgentResultDoubleSumObserver - implements AsynchronousInstrument.Callback< - io.opentelemetry.api.metrics.DoubleSumObserver.DoubleResult> { - - private final Callback metricUpdater; - - protected AgentResultDoubleSumObserver(Callback metricUpdater) { - this.metricUpdater = metricUpdater; - } - - @Override - public void update(io.opentelemetry.api.metrics.DoubleSumObserver.DoubleResult result) { - metricUpdater.update(new ApplicationResultDoubleSumObserver(result)); - } - } - - static class ApplicationResultDoubleSumObserver implements DoubleResult { - - private final io.opentelemetry.api.metrics.DoubleSumObserver.DoubleResult - agentResultDoubleSumObserver; - - public ApplicationResultDoubleSumObserver( - io.opentelemetry.api.metrics.DoubleSumObserver.DoubleResult agentResultDoubleSumObserver) { - this.agentResultDoubleSumObserver = agentResultDoubleSumObserver; - } - - @Override - public void observe(double value, Labels labels) { - agentResultDoubleSumObserver.observe(value, LabelBridging.toAgent(labels)); - } - } - - static class Builder implements DoubleSumObserver.Builder { - - private final io.opentelemetry.api.metrics.DoubleSumObserver.Builder agentBuilder; - - protected Builder(io.opentelemetry.api.metrics.DoubleSumObserver.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public DoubleSumObserver.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public DoubleSumObserver.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public DoubleSumObserver build() { - return new ApplicationDoubleSumObserver(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleUpDownCounter.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleUpDownCounter.java deleted file mode 100644 index 3077064bbf..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleUpDownCounter.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.DoubleUpDownCounter; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationDoubleUpDownCounter implements DoubleUpDownCounter { - - private final io.opentelemetry.api.metrics.DoubleUpDownCounter agentDoubleUpDownCounter; - - ApplicationDoubleUpDownCounter( - io.opentelemetry.api.metrics.DoubleUpDownCounter agentDoubleUpDownCounter) { - this.agentDoubleUpDownCounter = agentDoubleUpDownCounter; - } - - io.opentelemetry.api.metrics.DoubleUpDownCounter getAgentDoubleUpDownCounter() { - return agentDoubleUpDownCounter; - } - - @Override - public void add(double delta, Labels labels) { - agentDoubleUpDownCounter.add(delta, LabelBridging.toAgent(labels)); - } - - @Override - public void add(double v) { - agentDoubleUpDownCounter.add(v); - } - - @Override - public BoundDoubleUpDownCounter bind(Labels labels) { - return new BoundInstrument(agentDoubleUpDownCounter.bind(LabelBridging.toAgent(labels))); - } - - static class BoundInstrument implements BoundDoubleUpDownCounter { - - private final io.opentelemetry.api.metrics.DoubleUpDownCounter.BoundDoubleUpDownCounter - agentBoundDoubleUpDownCounter; - - BoundInstrument( - io.opentelemetry.api.metrics.DoubleUpDownCounter.BoundDoubleUpDownCounter - agentBoundDoubleUpDownCounter) { - this.agentBoundDoubleUpDownCounter = agentBoundDoubleUpDownCounter; - } - - @Override - public void add(double delta) { - agentBoundDoubleUpDownCounter.add(delta); - } - - @Override - public void unbind() { - agentBoundDoubleUpDownCounter.unbind(); - } - } - - static class Builder implements DoubleUpDownCounter.Builder { - - private final io.opentelemetry.api.metrics.DoubleUpDownCounter.Builder agentBuilder; - - Builder(io.opentelemetry.api.metrics.DoubleUpDownCounter.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public DoubleUpDownCounter.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public DoubleUpDownCounter.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public DoubleUpDownCounter build() { - return new ApplicationDoubleUpDownCounter(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleUpDownSumObserver.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleUpDownSumObserver.java deleted file mode 100644 index 79c7e6a5bb..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleUpDownSumObserver.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.DoubleUpDownSumObserver; -import io.opentelemetry.api.metrics.AsynchronousInstrument; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationDoubleUpDownSumObserver implements DoubleUpDownSumObserver { - - private final io.opentelemetry.api.metrics.DoubleUpDownSumObserver agentDoubleUpDownSumObserver; - - protected ApplicationDoubleUpDownSumObserver( - io.opentelemetry.api.metrics.DoubleUpDownSumObserver agentDoubleUpDownSumObserver) { - this.agentDoubleUpDownSumObserver = agentDoubleUpDownSumObserver; - } - - @Override - public void setCallback(Callback metricUpdater) { - agentDoubleUpDownSumObserver.setCallback(new AgentResultDoubleUpDownSumObserver(metricUpdater)); - } - - static class AgentResultDoubleUpDownSumObserver - implements AsynchronousInstrument.Callback< - io.opentelemetry.api.metrics.DoubleUpDownSumObserver.DoubleResult> { - - private final Callback metricUpdater; - - protected AgentResultDoubleUpDownSumObserver(Callback metricUpdater) { - this.metricUpdater = metricUpdater; - } - - @Override - public void update(io.opentelemetry.api.metrics.DoubleUpDownSumObserver.DoubleResult result) { - metricUpdater.update(new ApplicationResultDoubleUpDownSumObserver(result)); - } - } - - static class ApplicationResultDoubleUpDownSumObserver implements DoubleResult { - - private final io.opentelemetry.api.metrics.DoubleUpDownSumObserver.DoubleResult - agentResultDoubleUpDownSumObserver; - - public ApplicationResultDoubleUpDownSumObserver( - io.opentelemetry.api.metrics.DoubleUpDownSumObserver.DoubleResult - agentResultDoubleUpDownSumObserver) { - this.agentResultDoubleUpDownSumObserver = agentResultDoubleUpDownSumObserver; - } - - @Override - public void observe(double value, Labels labels) { - agentResultDoubleUpDownSumObserver.observe(value, LabelBridging.toAgent(labels)); - } - } - - static class Builder implements DoubleUpDownSumObserver.Builder { - - private final io.opentelemetry.api.metrics.DoubleUpDownSumObserver.Builder agentBuilder; - - protected Builder(io.opentelemetry.api.metrics.DoubleUpDownSumObserver.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public DoubleUpDownSumObserver.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public DoubleUpDownSumObserver.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public DoubleUpDownSumObserver build() { - return new ApplicationDoubleUpDownSumObserver(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleValueObserver.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleValueObserver.java deleted file mode 100644 index 5f64430929..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleValueObserver.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.DoubleValueObserver; -import io.opentelemetry.api.metrics.AsynchronousInstrument; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationDoubleValueObserver implements DoubleValueObserver { - - private final io.opentelemetry.api.metrics.DoubleValueObserver agentDoubleValueObserver; - - protected ApplicationDoubleValueObserver( - io.opentelemetry.api.metrics.DoubleValueObserver agentDoubleValueObserver) { - this.agentDoubleValueObserver = agentDoubleValueObserver; - } - - @Override - public void setCallback(Callback metricUpdater) { - agentDoubleValueObserver.setCallback(new AgentResultDoubleValueObserver(metricUpdater)); - } - - static class AgentResultDoubleValueObserver - implements AsynchronousInstrument.Callback< - io.opentelemetry.api.metrics.DoubleValueObserver.DoubleResult> { - - private final Callback metricUpdater; - - protected AgentResultDoubleValueObserver(Callback metricUpdater) { - this.metricUpdater = metricUpdater; - } - - @Override - public void update(io.opentelemetry.api.metrics.DoubleValueObserver.DoubleResult result) { - metricUpdater.update(new ApplicationResultDoubleValueObserver(result)); - } - } - - static class ApplicationResultDoubleValueObserver implements DoubleResult { - - private final io.opentelemetry.api.metrics.DoubleValueObserver.DoubleResult - agentResultDoubleValueObserver; - - public ApplicationResultDoubleValueObserver( - io.opentelemetry.api.metrics.DoubleValueObserver.DoubleResult - agentResultDoubleValueObserver) { - this.agentResultDoubleValueObserver = agentResultDoubleValueObserver; - } - - @Override - public void observe(double value, Labels labels) { - agentResultDoubleValueObserver.observe(value, LabelBridging.toAgent(labels)); - } - } - - static class Builder implements DoubleValueObserver.Builder { - - private final io.opentelemetry.api.metrics.DoubleValueObserver.Builder agentBuilder; - - protected Builder(io.opentelemetry.api.metrics.DoubleValueObserver.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public DoubleValueObserver.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public DoubleValueObserver.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public DoubleValueObserver build() { - return new ApplicationDoubleValueObserver(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleValueRecorder.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleValueRecorder.java deleted file mode 100644 index cea1963f9c..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationDoubleValueRecorder.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.DoubleValueRecorder; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationDoubleValueRecorder implements DoubleValueRecorder { - - private final io.opentelemetry.api.metrics.DoubleValueRecorder agentDoubleValueRecorder; - - protected ApplicationDoubleValueRecorder( - io.opentelemetry.api.metrics.DoubleValueRecorder agentDoubleValueRecorder) { - this.agentDoubleValueRecorder = agentDoubleValueRecorder; - } - - protected io.opentelemetry.api.metrics.DoubleValueRecorder getAgentDoubleValueRecorder() { - return agentDoubleValueRecorder; - } - - @Override - public void record(double delta, Labels labels) { - agentDoubleValueRecorder.record(delta, LabelBridging.toAgent(labels)); - } - - @Override - public void record(double v) { - agentDoubleValueRecorder.record(v); - } - - @Override - public BoundDoubleValueRecorder bind(Labels labels) { - return new BoundInstrument(agentDoubleValueRecorder.bind(LabelBridging.toAgent(labels))); - } - - static class BoundInstrument implements DoubleValueRecorder.BoundDoubleValueRecorder { - - private final io.opentelemetry.api.metrics.DoubleValueRecorder.BoundDoubleValueRecorder - agentBoundDoubleMeasure; - - public BoundInstrument( - io.opentelemetry.api.metrics.DoubleValueRecorder.BoundDoubleValueRecorder - agentBoundDoubleMeasure) { - this.agentBoundDoubleMeasure = agentBoundDoubleMeasure; - } - - @Override - public void record(double delta) { - agentBoundDoubleMeasure.record(delta); - } - - @Override - public void unbind() { - agentBoundDoubleMeasure.unbind(); - } - } - - static class Builder implements DoubleValueRecorder.Builder { - - private final io.opentelemetry.api.metrics.DoubleValueRecorder.Builder agentBuilder; - - public Builder(io.opentelemetry.api.metrics.DoubleValueRecorder.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public DoubleValueRecorder.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public DoubleValueRecorder.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public DoubleValueRecorder build() { - return new ApplicationDoubleValueRecorder(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongCounter.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongCounter.java deleted file mode 100644 index 045fa2b88a..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongCounter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.LongCounter; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationLongCounter implements LongCounter { - - private final io.opentelemetry.api.metrics.LongCounter agentLongCounter; - - ApplicationLongCounter(io.opentelemetry.api.metrics.LongCounter agentLongCounter) { - this.agentLongCounter = agentLongCounter; - } - - io.opentelemetry.api.metrics.LongCounter getAgentLongCounter() { - return agentLongCounter; - } - - @Override - public void add(long delta, Labels labels) { - agentLongCounter.add(delta, LabelBridging.toAgent(labels)); - } - - @Override - public void add(long l) { - agentLongCounter.add(l); - } - - @Override - public BoundLongCounter bind(Labels labels) { - return new BoundInstrument(agentLongCounter.bind(LabelBridging.toAgent(labels))); - } - - static class BoundInstrument implements LongCounter.BoundLongCounter { - - private final io.opentelemetry.api.metrics.LongCounter.BoundLongCounter agentBoundLongCounter; - - BoundInstrument( - io.opentelemetry.api.metrics.LongCounter.BoundLongCounter agentBoundLongCounter) { - this.agentBoundLongCounter = agentBoundLongCounter; - } - - @Override - public void add(long delta) { - agentBoundLongCounter.add(delta); - } - - @Override - public void unbind() { - agentBoundLongCounter.unbind(); - } - } - - static class Builder implements LongCounter.Builder { - - private final io.opentelemetry.api.metrics.LongCounter.Builder agentBuilder; - - Builder(io.opentelemetry.api.metrics.LongCounter.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public LongCounter.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public LongCounter.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public LongCounter build() { - return new ApplicationLongCounter(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongSumObserver.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongSumObserver.java deleted file mode 100644 index 061d7e32fa..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongSumObserver.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.LongSumObserver; -import io.opentelemetry.api.metrics.AsynchronousInstrument; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationLongSumObserver implements LongSumObserver { - - private final io.opentelemetry.api.metrics.LongSumObserver agentLongSumObserver; - - protected ApplicationLongSumObserver( - io.opentelemetry.api.metrics.LongSumObserver agentLongSumObserver) { - this.agentLongSumObserver = agentLongSumObserver; - } - - @Override - public void setCallback(Callback metricUpdater) { - agentLongSumObserver.setCallback(new AgentResultLongSumObserver(metricUpdater)); - } - - static class AgentResultLongSumObserver - implements AsynchronousInstrument.Callback< - io.opentelemetry.api.metrics.LongSumObserver.LongResult> { - - private final Callback metricUpdater; - - protected AgentResultLongSumObserver(Callback metricUpdater) { - this.metricUpdater = metricUpdater; - } - - @Override - public void update(io.opentelemetry.api.metrics.LongSumObserver.LongResult result) { - metricUpdater.update(new ApplicationResultLongSumObserver(result)); - } - } - - static class ApplicationResultLongSumObserver implements LongResult { - - private final io.opentelemetry.api.metrics.LongSumObserver.LongResult - agentResultLongSumObserver; - - public ApplicationResultLongSumObserver( - io.opentelemetry.api.metrics.LongSumObserver.LongResult agentResultLongSumObserver) { - this.agentResultLongSumObserver = agentResultLongSumObserver; - } - - @Override - public void observe(long value, Labels labels) { - agentResultLongSumObserver.observe(value, LabelBridging.toAgent(labels)); - } - } - - static class Builder implements LongSumObserver.Builder { - - private final io.opentelemetry.api.metrics.LongSumObserver.Builder agentBuilder; - - protected Builder(io.opentelemetry.api.metrics.LongSumObserver.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public LongSumObserver.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public LongSumObserver.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public LongSumObserver build() { - return new ApplicationLongSumObserver(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongUpDownCounter.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongUpDownCounter.java deleted file mode 100644 index 557f05e393..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongUpDownCounter.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.LongUpDownCounter; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationLongUpDownCounter implements LongUpDownCounter { - - private final io.opentelemetry.api.metrics.LongUpDownCounter agentLongUpDownCounter; - - ApplicationLongUpDownCounter( - io.opentelemetry.api.metrics.LongUpDownCounter agentLongUpDownCounter) { - this.agentLongUpDownCounter = agentLongUpDownCounter; - } - - io.opentelemetry.api.metrics.LongUpDownCounter getAgentLongUpDownCounter() { - return agentLongUpDownCounter; - } - - @Override - public void add(long delta, Labels labels) { - agentLongUpDownCounter.add(delta, LabelBridging.toAgent(labels)); - } - - @Override - public void add(long l) { - agentLongUpDownCounter.add(l); - } - - @Override - public BoundLongUpDownCounter bind(Labels labels) { - return new BoundInstrument(agentLongUpDownCounter.bind(LabelBridging.toAgent(labels))); - } - - static class BoundInstrument implements BoundLongUpDownCounter { - - private final io.opentelemetry.api.metrics.LongUpDownCounter.BoundLongUpDownCounter - agentBoundLongUpDownCounter; - - BoundInstrument( - io.opentelemetry.api.metrics.LongUpDownCounter.BoundLongUpDownCounter - agentBoundLongUpDownCounter) { - this.agentBoundLongUpDownCounter = agentBoundLongUpDownCounter; - } - - @Override - public void add(long delta) { - agentBoundLongUpDownCounter.add(delta); - } - - @Override - public void unbind() { - agentBoundLongUpDownCounter.unbind(); - } - } - - static class Builder implements LongUpDownCounter.Builder { - - private final io.opentelemetry.api.metrics.LongUpDownCounter.Builder agentBuilder; - - Builder(io.opentelemetry.api.metrics.LongUpDownCounter.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public LongUpDownCounter.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public LongUpDownCounter.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public LongUpDownCounter build() { - return new ApplicationLongUpDownCounter(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongUpDownSumObserver.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongUpDownSumObserver.java deleted file mode 100644 index 4b55a83a76..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongUpDownSumObserver.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.LongUpDownSumObserver; -import io.opentelemetry.api.metrics.AsynchronousInstrument; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationLongUpDownSumObserver implements LongUpDownSumObserver { - - private final io.opentelemetry.api.metrics.LongUpDownSumObserver agentLongUpDownSumObserver; - - protected ApplicationLongUpDownSumObserver( - io.opentelemetry.api.metrics.LongUpDownSumObserver agentLongUpDownSumObserver) { - this.agentLongUpDownSumObserver = agentLongUpDownSumObserver; - } - - @Override - public void setCallback(Callback metricUpdater) { - agentLongUpDownSumObserver.setCallback(new AgentResultLongUpDownSumObserver(metricUpdater)); - } - - static class AgentResultLongUpDownSumObserver - implements AsynchronousInstrument.Callback< - io.opentelemetry.api.metrics.LongUpDownSumObserver.LongResult> { - - private final Callback metricUpdater; - - protected AgentResultLongUpDownSumObserver(Callback metricUpdater) { - this.metricUpdater = metricUpdater; - } - - @Override - public void update(io.opentelemetry.api.metrics.LongUpDownSumObserver.LongResult result) { - metricUpdater.update(new ApplicationResultLongUpDownSumObserver(result)); - } - } - - static class ApplicationResultLongUpDownSumObserver implements LongResult { - - private final io.opentelemetry.api.metrics.LongUpDownSumObserver.LongResult - agentResultLongUpDownSumObserver; - - public ApplicationResultLongUpDownSumObserver( - io.opentelemetry.api.metrics.LongUpDownSumObserver.LongResult - agentResultLongUpDownSumObserver) { - this.agentResultLongUpDownSumObserver = agentResultLongUpDownSumObserver; - } - - @Override - public void observe(long value, Labels labels) { - agentResultLongUpDownSumObserver.observe(value, LabelBridging.toAgent(labels)); - } - } - - static class Builder implements LongUpDownSumObserver.Builder { - - private final io.opentelemetry.api.metrics.LongUpDownSumObserver.Builder agentBuilder; - - protected Builder(io.opentelemetry.api.metrics.LongUpDownSumObserver.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public LongUpDownSumObserver.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public LongUpDownSumObserver.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public LongUpDownSumObserver build() { - return new ApplicationLongUpDownSumObserver(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongValueObserver.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongValueObserver.java deleted file mode 100644 index 94db756694..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongValueObserver.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.LongValueObserver; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationLongValueObserver implements LongValueObserver { - - private final io.opentelemetry.api.metrics.LongValueObserver agentLongValueObserver; - - public ApplicationLongValueObserver( - io.opentelemetry.api.metrics.LongValueObserver agentLongValueObserver) { - this.agentLongValueObserver = agentLongValueObserver; - } - - @Override - public void setCallback(Callback metricUpdater) { - agentLongValueObserver.setCallback(new AgentResultLongValueObserver(metricUpdater)); - } - - public static class AgentResultLongValueObserver - implements io.opentelemetry.api.metrics.AsynchronousInstrument.Callback< - io.opentelemetry.api.metrics.LongValueObserver.LongResult> { - - private final Callback metricUpdater; - - public AgentResultLongValueObserver(Callback metricUpdater) { - this.metricUpdater = metricUpdater; - } - - @Override - public void update(io.opentelemetry.api.metrics.LongValueObserver.LongResult result) { - metricUpdater.update(new ApplicationResultLongValueObserver(result)); - } - } - - public static class ApplicationResultLongValueObserver implements LongResult { - - private final io.opentelemetry.api.metrics.LongValueObserver.LongResult - agentResultLongValueObserver; - - public ApplicationResultLongValueObserver( - io.opentelemetry.api.metrics.LongValueObserver.LongResult agentResultLongValueObserver) { - this.agentResultLongValueObserver = agentResultLongValueObserver; - } - - @Override - public void observe(long value, Labels labels) { - agentResultLongValueObserver.observe(value, LabelBridging.toAgent(labels)); - } - } - - static class Builder implements LongValueObserver.Builder { - - private final io.opentelemetry.api.metrics.LongValueObserver.Builder agentBuilder; - - public Builder(io.opentelemetry.api.metrics.LongValueObserver.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public LongValueObserver.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public LongValueObserver.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public LongValueObserver build() { - return new ApplicationLongValueObserver(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongValueRecorder.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongValueRecorder.java deleted file mode 100644 index 6bfc83dee2..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationLongValueRecorder.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.common.Labels; -import application.io.opentelemetry.api.metrics.LongValueRecorder; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.LabelBridging; - -class ApplicationLongValueRecorder implements LongValueRecorder { - - private final io.opentelemetry.api.metrics.LongValueRecorder agentLongValueRecorder; - - protected ApplicationLongValueRecorder( - io.opentelemetry.api.metrics.LongValueRecorder agentLongValueRecorder) { - this.agentLongValueRecorder = agentLongValueRecorder; - } - - public io.opentelemetry.api.metrics.LongValueRecorder getAgentLongValueRecorder() { - return agentLongValueRecorder; - } - - @Override - public void record(long delta, Labels labels) { - agentLongValueRecorder.record(delta, LabelBridging.toAgent(labels)); - } - - @Override - public void record(long l) { - agentLongValueRecorder.record(l); - } - - @Override - public BoundLongValueRecorder bind(Labels labels) { - return new BoundInstrument(agentLongValueRecorder.bind(LabelBridging.toAgent(labels))); - } - - static class BoundInstrument implements LongValueRecorder.BoundLongValueRecorder { - - private final io.opentelemetry.api.metrics.LongValueRecorder.BoundLongValueRecorder - agentBoundLongValueRecorder; - - protected BoundInstrument( - io.opentelemetry.api.metrics.LongValueRecorder.BoundLongValueRecorder - agentBoundLongValueRecorder) { - this.agentBoundLongValueRecorder = agentBoundLongValueRecorder; - } - - @Override - public void record(long delta) { - agentBoundLongValueRecorder.record(delta); - } - - @Override - public void unbind() { - agentBoundLongValueRecorder.unbind(); - } - } - - static class Builder implements LongValueRecorder.Builder { - - private final io.opentelemetry.api.metrics.LongValueRecorder.Builder agentBuilder; - - protected Builder(io.opentelemetry.api.metrics.LongValueRecorder.Builder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public LongValueRecorder.Builder setDescription(String description) { - agentBuilder.setDescription(description); - return this; - } - - @Override - public LongValueRecorder.Builder setUnit(String unit) { - agentBuilder.setUnit(unit); - return this; - } - - @Override - public LongValueRecorder build() { - return new ApplicationLongValueRecorder(agentBuilder.build()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationMeter.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationMeter.java deleted file mode 100644 index 5d00e79f5f..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationMeter.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.metrics.BatchRecorder; -import application.io.opentelemetry.api.metrics.DoubleCounter; -import application.io.opentelemetry.api.metrics.DoubleSumObserver; -import application.io.opentelemetry.api.metrics.DoubleUpDownCounter; -import application.io.opentelemetry.api.metrics.DoubleUpDownSumObserver; -import application.io.opentelemetry.api.metrics.DoubleValueObserver; -import application.io.opentelemetry.api.metrics.DoubleValueRecorder; -import application.io.opentelemetry.api.metrics.LongCounter; -import application.io.opentelemetry.api.metrics.LongSumObserver; -import application.io.opentelemetry.api.metrics.LongUpDownCounter; -import application.io.opentelemetry.api.metrics.LongUpDownSumObserver; -import application.io.opentelemetry.api.metrics.LongValueObserver; -import application.io.opentelemetry.api.metrics.LongValueRecorder; -import application.io.opentelemetry.api.metrics.Meter; - -class ApplicationMeter implements Meter { - - private final io.opentelemetry.api.metrics.Meter agentMeter; - - ApplicationMeter(io.opentelemetry.api.metrics.Meter agentMeter) { - this.agentMeter = agentMeter; - } - - @Override - public DoubleCounter.Builder doubleCounterBuilder(String name) { - return new ApplicationDoubleCounter.Builder(agentMeter.doubleCounterBuilder(name)); - } - - @Override - public LongCounter.Builder longCounterBuilder(String name) { - return new ApplicationLongCounter.Builder(agentMeter.longCounterBuilder(name)); - } - - @Override - public DoubleUpDownCounter.Builder doubleUpDownCounterBuilder(String name) { - return new ApplicationDoubleUpDownCounter.Builder(agentMeter.doubleUpDownCounterBuilder(name)); - } - - @Override - public LongUpDownCounter.Builder longUpDownCounterBuilder(String name) { - return new ApplicationLongUpDownCounter.Builder(agentMeter.longUpDownCounterBuilder(name)); - } - - @Override - public DoubleValueRecorder.Builder doubleValueRecorderBuilder(String name) { - return new ApplicationDoubleValueRecorder.Builder(agentMeter.doubleValueRecorderBuilder(name)); - } - - @Override - public LongValueRecorder.Builder longValueRecorderBuilder(String name) { - return new ApplicationLongValueRecorder.Builder(agentMeter.longValueRecorderBuilder(name)); - } - - @Override - public DoubleSumObserver.Builder doubleSumObserverBuilder(String name) { - return new ApplicationDoubleSumObserver.Builder(agentMeter.doubleSumObserverBuilder(name)); - } - - @Override - public LongSumObserver.Builder longSumObserverBuilder(String name) { - return new ApplicationLongSumObserver.Builder(agentMeter.longSumObserverBuilder(name)); - } - - @Override - public DoubleUpDownSumObserver.Builder doubleUpDownSumObserverBuilder(String name) { - return new ApplicationDoubleUpDownSumObserver.Builder( - agentMeter.doubleUpDownSumObserverBuilder(name)); - } - - @Override - public LongUpDownSumObserver.Builder longUpDownSumObserverBuilder(String name) { - return new ApplicationLongUpDownSumObserver.Builder( - agentMeter.longUpDownSumObserverBuilder(name)); - } - - @Override - public DoubleValueObserver.Builder doubleValueObserverBuilder(String name) { - return new ApplicationDoubleValueObserver.Builder(agentMeter.doubleValueObserverBuilder(name)); - } - - @Override - public LongValueObserver.Builder longValueObserverBuilder(String name) { - return new ApplicationLongValueObserver.Builder(agentMeter.longValueObserverBuilder(name)); - } - - @Override - public BatchRecorder newBatchRecorder(String... keyValuePairs) { - return new ApplicationBatchRecorder(agentMeter.newBatchRecorder(keyValuePairs)); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationMeterProvider.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationMeterProvider.java deleted file mode 100644 index d64e01a3ac..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/metrics/ApplicationMeterProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.metrics; - -import application.io.opentelemetry.api.metrics.Meter; -import application.io.opentelemetry.api.metrics.MeterProvider; - -public class ApplicationMeterProvider implements MeterProvider { - - @Override - public Meter get(String instrumentationName) { - return new ApplicationMeter( - io.opentelemetry.api.OpenTelemetry.getGlobalMeterProvider().get(instrumentationName)); - } - - @Override - public Meter get(String instrumentationName, String instrumentationVersion) { - return new ApplicationMeter( - io.opentelemetry.api.OpenTelemetry.getGlobalMeterProvider() - .get(instrumentationName, instrumentationVersion)); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationSpan.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationSpan.java deleted file mode 100644 index 174ab788dd..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationSpan.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace; - -import static io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging.toAgentOrNull; - -import application.io.opentelemetry.api.common.AttributeKey; -import application.io.opentelemetry.api.common.Attributes; -import application.io.opentelemetry.api.trace.Span; -import application.io.opentelemetry.api.trace.SpanBuilder; -import application.io.opentelemetry.api.trace.SpanContext; -import application.io.opentelemetry.api.trace.StatusCode; -import application.io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; -import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class ApplicationSpan implements Span { - - private final io.opentelemetry.api.trace.Span agentSpan; - - ApplicationSpan(io.opentelemetry.api.trace.Span agentSpan) { - this.agentSpan = agentSpan; - } - - io.opentelemetry.api.trace.Span getAgentSpan() { - return agentSpan; - } - - @Override - public Span setAttribute(String key, String value) { - agentSpan.setAttribute(key, value); - return this; - } - - @Override - public Span setAttribute(String key, long value) { - agentSpan.setAttribute(key, value); - return this; - } - - @Override - public Span setAttribute(String key, double value) { - agentSpan.setAttribute(key, value); - return this; - } - - @Override - public Span setAttribute(String key, boolean value) { - agentSpan.setAttribute(key, value); - return this; - } - - @Override - public Span setAttribute(AttributeKey applicationKey, T value) { - io.opentelemetry.api.common.AttributeKey agentKey = Bridging.toAgent(applicationKey); - if (agentKey != null) { - agentSpan.setAttribute(agentKey, value); - } - return this; - } - - @Override - public Span addEvent(String name) { - agentSpan.addEvent(name); - return this; - } - - @Override - public Span addEvent(String name, long timestamp, TimeUnit unit) { - agentSpan.addEvent(name, timestamp, unit); - return this; - } - - @Override - public Span addEvent(String name, Attributes applicationAttributes) { - agentSpan.addEvent(name, Bridging.toAgent(applicationAttributes)); - return this; - } - - @Override - public Span addEvent( - String name, Attributes applicationAttributes, long timestamp, TimeUnit unit) { - agentSpan.addEvent(name, Bridging.toAgent(applicationAttributes), timestamp, unit); - return this; - } - - @Override - public Span setStatus(StatusCode status) { - agentSpan.setStatus(Bridging.toAgent(status)); - return this; - } - - @Override - public Span setStatus(StatusCode status, String description) { - agentSpan.setStatus(Bridging.toAgent(status), description); - return this; - } - - @Override - public Span recordException(Throwable throwable) { - agentSpan.recordException(throwable); - return this; - } - - @Override - public Span recordException(Throwable throwable, Attributes attributes) { - agentSpan.recordException(throwable, Bridging.toAgent(attributes)); - return this; - } - - @Override - public Span updateName(String name) { - agentSpan.updateName(name); - return this; - } - - @Override - public void end() { - agentSpan.end(); - } - - @Override - public void end(long timestamp, TimeUnit unit) { - agentSpan.end(timestamp, unit); - } - - @Override - public SpanContext getSpanContext() { - return Bridging.toApplication(agentSpan.getSpanContext()); - } - - @Override - public boolean isRecording() { - return agentSpan.isRecording(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof ApplicationSpan)) { - return false; - } - ApplicationSpan other = (ApplicationSpan) obj; - return agentSpan.equals(other.agentSpan); - } - - @Override - public int hashCode() { - return agentSpan.hashCode(); - } - - static class Builder implements SpanBuilder { - - private static final Logger log = LoggerFactory.getLogger(Builder.class); - - private final io.opentelemetry.api.trace.SpanBuilder agentBuilder; - - Builder(io.opentelemetry.api.trace.SpanBuilder agentBuilder) { - this.agentBuilder = agentBuilder; - } - - @Override - public SpanBuilder setParent(Context applicationContext) { - agentBuilder.setParent(AgentContextStorage.getAgentContext(applicationContext)); - return this; - } - - @Override - public SpanBuilder setNoParent() { - agentBuilder.setNoParent(); - return this; - } - - @Override - public SpanBuilder addLink(SpanContext applicationSpanContext) { - agentBuilder.addLink(Bridging.toAgent(applicationSpanContext)); - return this; - } - - @Override - public SpanBuilder addLink( - SpanContext applicationSpanContext, Attributes applicationAttributes) { - agentBuilder.addLink(Bridging.toAgent(applicationSpanContext)); - return this; - } - - @Override - public SpanBuilder setAttribute(String key, String value) { - agentBuilder.setAttribute(key, value); - return this; - } - - @Override - public SpanBuilder setAttribute(String key, long value) { - agentBuilder.setAttribute(key, value); - return this; - } - - @Override - public SpanBuilder setAttribute(String key, double value) { - agentBuilder.setAttribute(key, value); - return this; - } - - @Override - public SpanBuilder setAttribute(String key, boolean value) { - agentBuilder.setAttribute(key, value); - return this; - } - - @Override - public SpanBuilder setAttribute(AttributeKey applicationKey, T value) { - io.opentelemetry.api.common.AttributeKey agentKey = Bridging.toAgent(applicationKey); - if (agentKey != null) { - agentBuilder.setAttribute(agentKey, value); - } - return this; - } - - @Override - public SpanBuilder setSpanKind(Span.Kind applicationSpanKind) { - io.opentelemetry.api.trace.Span.Kind agentSpanKind = toAgentOrNull(applicationSpanKind); - if (agentSpanKind != null) { - agentBuilder.setSpanKind(agentSpanKind); - } - return this; - } - - @Override - public SpanBuilder setStartTimestamp(long startTimestamp, TimeUnit unit) { - agentBuilder.setStartTimestamp(startTimestamp, unit); - return this; - } - - @Override - public Span startSpan() { - return new ApplicationSpan(agentBuilder.startSpan()); - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationTracer.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationTracer.java deleted file mode 100644 index 04bb66da5a..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationTracer.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace; - -import application.io.opentelemetry.api.trace.SpanBuilder; -import application.io.opentelemetry.api.trace.Tracer; - -class ApplicationTracer implements Tracer { - - private final io.opentelemetry.api.trace.Tracer agentTracer; - - ApplicationTracer(io.opentelemetry.api.trace.Tracer agentTracer) { - this.agentTracer = agentTracer; - } - - @Override - public SpanBuilder spanBuilder(String spanName) { - return new ApplicationSpan.Builder(agentTracer.spanBuilder(spanName)); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationTracerProvider.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationTracerProvider.java deleted file mode 100644 index d312e20e0f..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/ApplicationTracerProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace; - -import application.io.opentelemetry.api.internal.Obfuscated; -import application.io.opentelemetry.api.trace.Tracer; -import application.io.opentelemetry.api.trace.TracerProvider; -import java.util.concurrent.atomic.AtomicBoolean; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ApplicationTracerProvider implements TracerProvider, Obfuscated { - - private static final Logger log = LoggerFactory.getLogger(ApplicationTracerProvider.class); - - private static final AtomicBoolean messageAlreadyLogged = new AtomicBoolean(); - - private final TracerProvider applicationOriginalTracerProvider; - - public ApplicationTracerProvider(TracerProvider applicationOriginalTracerProvider) { - this.applicationOriginalTracerProvider = applicationOriginalTracerProvider; - } - - @Override - public Tracer get(String instrumentationName) { - return new ApplicationTracer( - io.opentelemetry.api.OpenTelemetry.getGlobalTracer(instrumentationName)); - } - - @Override - public Tracer get(String instrumentationName, String instrumentationVersion) { - return new ApplicationTracer( - io.opentelemetry.api.OpenTelemetry.getGlobalTracerProvider() - .get(instrumentationName, instrumentationVersion)); - } - - // this is called by OpenTelemetrySdk, which expects to get back a real TracerProviderSdk - @Override - public Object unobfuscate() { - if (!messageAlreadyLogged.getAndSet(true)) { - String message = - "direct usage of the OpenTelemetry SDK, e.g. using OpenTelemetrySdk.getTracerProvider()" - + " instead of OpenTelemetry.getGlobalTracerProvider(), is not supported when running agent" - + " (see https://github.com/open-telemetry/opentelemetry-java-instrumentation#troubleshooting" - + " for how to run with debug logging, which will log stack trace with this message)"; - if (log.isDebugEnabled()) { - log.debug(message, new Exception("stack trace")); - } else { - log.info(message); - } - } - return ((Obfuscated) applicationOriginalTracerProvider).unobfuscate(); - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/Bridging.java b/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/Bridging.java deleted file mode 100644 index 1da267585d..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/trace/Bridging.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace; - -import application.io.opentelemetry.api.common.AttributeConsumer; -import application.io.opentelemetry.api.common.AttributeKey; -import application.io.opentelemetry.api.common.Attributes; -import application.io.opentelemetry.api.trace.Span; -import application.io.opentelemetry.api.trace.SpanContext; -import application.io.opentelemetry.api.trace.StatusCode; -import application.io.opentelemetry.api.trace.TraceState; -import application.io.opentelemetry.api.trace.TraceStateBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class translates between the (unshaded) OpenTelemetry API that the application brings and - * the (shaded) OpenTelemetry API that is used by the agent. - * - *

"application.io.opentelemetry.*" refers to the (unshaded) OpenTelemetry API that the - * application brings (as those references will be translated during the build to remove the - * "application." prefix). - * - *

"io.opentelemetry.*" refers to the (shaded) OpenTelemetry API that is used by the agent (as - * those references will later be shaded). - * - *

Also see comments in this module's gradle file. - */ -public class Bridging { - - private static final Logger log = LoggerFactory.getLogger(Bridging.class); - - // this is just an optimization to save some byte array allocations - public static final ThreadLocal BUFFER = new ThreadLocal<>(); - - public static Span toApplication(io.opentelemetry.api.trace.Span agentSpan) { - if (!agentSpan.getSpanContext().isValid()) { - // no need to wrap - return Span.getInvalid(); - } else { - return new ApplicationSpan(agentSpan); - } - } - - public static SpanContext toApplication(io.opentelemetry.api.trace.SpanContext agentContext) { - if (agentContext.isRemote()) { - return SpanContext.createFromRemoteParent( - agentContext.getTraceIdAsHexString(), - agentContext.getSpanIdAsHexString(), - agentContext.getTraceFlags(), - toApplication(agentContext.getTraceState())); - } else { - return SpanContext.create( - agentContext.getTraceIdAsHexString(), - agentContext.getSpanIdAsHexString(), - agentContext.getTraceFlags(), - toApplication(agentContext.getTraceState())); - } - } - - private static TraceState toApplication(io.opentelemetry.api.trace.TraceState agentTraceState) { - TraceStateBuilder applicationTraceState = TraceState.builder(); - agentTraceState.forEach(applicationTraceState::set); - return applicationTraceState.build(); - } - - public static io.opentelemetry.api.trace.Span toAgentOrNull(Span applicationSpan) { - if (!applicationSpan.getSpanContext().isValid()) { - // no need to wrap - return io.opentelemetry.api.trace.Span.getInvalid(); - } else if (applicationSpan instanceof ApplicationSpan) { - return ((ApplicationSpan) applicationSpan).getAgentSpan(); - } else { - return null; - } - } - - public static io.opentelemetry.api.trace.Span.Kind toAgentOrNull(Span.Kind applicationSpanKind) { - try { - return io.opentelemetry.api.trace.Span.Kind.valueOf(applicationSpanKind.name()); - } catch (IllegalArgumentException e) { - log.debug("unexpected span kind: {}", applicationSpanKind.name()); - return null; - } - } - - public static io.opentelemetry.api.trace.SpanContext toAgent(SpanContext applicationContext) { - if (applicationContext.isRemote()) { - return io.opentelemetry.api.trace.SpanContext.createFromRemoteParent( - applicationContext.getTraceIdAsHexString(), - applicationContext.getSpanIdAsHexString(), - applicationContext.getTraceFlags(), - toAgent(applicationContext.getTraceState())); - } else { - return io.opentelemetry.api.trace.SpanContext.create( - applicationContext.getTraceIdAsHexString(), - applicationContext.getSpanIdAsHexString(), - applicationContext.getTraceFlags(), - toAgent(applicationContext.getTraceState())); - } - } - - public static io.opentelemetry.api.common.Attributes toAgent(Attributes applicationAttributes) { - final io.opentelemetry.api.common.AttributesBuilder agentAttributes = - io.opentelemetry.api.common.Attributes.builder(); - applicationAttributes.forEach( - new AttributeConsumer() { - @Override - public void accept(AttributeKey key, T value) { - io.opentelemetry.api.common.AttributeKey agentKey = toAgent(key); - if (agentKey != null) { - agentAttributes.put(agentKey, value); - } - } - }); - return agentAttributes.build(); - } - - // TODO optimize this by storing shaded AttributeKey inside of application AttributeKey instead of - // creating every time - @SuppressWarnings("unchecked") - public static io.opentelemetry.api.common.AttributeKey toAgent( - AttributeKey applicationKey) { - switch (applicationKey.getType()) { - case STRING: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.stringKey(applicationKey.getKey()); - case BOOLEAN: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.booleanKey(applicationKey.getKey()); - case LONG: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.longKey(applicationKey.getKey()); - case DOUBLE: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.doubleKey(applicationKey.getKey()); - case STRING_ARRAY: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.stringArrayKey(applicationKey.getKey()); - case BOOLEAN_ARRAY: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.booleanArrayKey(applicationKey.getKey()); - case LONG_ARRAY: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.longArrayKey(applicationKey.getKey()); - case DOUBLE_ARRAY: - return (io.opentelemetry.api.common.AttributeKey) - io.opentelemetry.api.common.AttributeKey.doubleArrayKey(applicationKey.getKey()); - default: - log.debug("unexpected attribute key type: {}", applicationKey.getType()); - return null; - } - } - - public static io.opentelemetry.api.trace.StatusCode toAgent(StatusCode applicationStatus) { - io.opentelemetry.api.trace.StatusCode agentCanonicalCode; - try { - agentCanonicalCode = io.opentelemetry.api.trace.StatusCode.valueOf(applicationStatus.name()); - } catch (IllegalArgumentException e) { - log.debug("unexpected status canonical code: {}", applicationStatus.name()); - return io.opentelemetry.api.trace.StatusCode.UNSET; - } - return agentCanonicalCode; - } - - private static io.opentelemetry.api.trace.TraceState toAgent(TraceState applicationTraceState) { - io.opentelemetry.api.trace.TraceStateBuilder agentTraceState = - io.opentelemetry.api.trace.TraceState.builder(); - applicationTraceState.forEach(agentTraceState::set); - return agentTraceState.build(); - } - - private static byte[] getBuffer() { - byte[] bytes = BUFFER.get(); - if (bytes == null) { - bytes = new byte[16]; - BUFFER.set(bytes); - } - return bytes; - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/test/groovy/ContextBridgeTest.groovy b/instrumentation/opentelemetry-api-1.0/src/test/groovy/ContextBridgeTest.groovy deleted file mode 100644 index 1b169368bd..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/test/groovy/ContextBridgeTest.groovy +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import application.io.opentelemetry.api.OpenTelemetry -import application.io.opentelemetry.api.trace.Span -import application.io.opentelemetry.context.Context -import application.io.opentelemetry.context.ContextKey -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.atomic.AtomicReference - -class ContextBridgeTest extends AgentTestRunner { - - private static final ContextKey ANIMAL = ContextKey.named("animal") - - private static final io.opentelemetry.context.ContextKey FOOD = - io.opentelemetry.context.ContextKey.named("food") - private static final io.opentelemetry.context.ContextKey COUNTRY = - io.opentelemetry.context.ContextKey.named("country") - - def "agent and application mix"() { - expect: - def agentContext = io.opentelemetry.context.Context.current().with(COUNTRY, "japan") - io.opentelemetry.context.Context.current().get(COUNTRY) == null - agentContext.makeCurrent().withCloseable { - io.opentelemetry.context.Context.current().get(COUNTRY) == "japan" - Context.current().with(ANIMAL, "cat").makeCurrent().withCloseable { - Context.current().get(ANIMAL) == "cat" - io.opentelemetry.context.Context.current().get(COUNTRY) == "japan" - - def agentContext2 = io.opentelemetry.context.Context.current().with(FOOD, "cheese") - io.opentelemetry.context.Context.current().get(FOOD) == null - agentContext2.makeCurrent().withCloseable { - io.opentelemetry.context.Context.current().get(FOOD) == "cheese" - io.opentelemetry.context.Context.current().get(COUNTRY) == "japan" - Context.current().get(ANIMAL) == "cat" - } - } - } - } - - // The difference between "standard" context interop and our bridge is that with normal interop, - // keys are still isolated completely. We have special logic to share the same data for our known - // types like span. - def "agent and application share span"() { - when: - def applicationTracer = OpenTelemetry.getGlobalTracer("test") - def agentTracer = io.opentelemetry.api.OpenTelemetry.getGlobalTracer("test") - - then: - !Span.current().spanContext.isValid() - !io.opentelemetry.api.trace.Span.current().spanContext.isValid() - - def applicationSpan = applicationTracer.spanBuilder("test1").startSpan() - applicationSpan.spanContext.isValid() - applicationSpan.makeCurrent().withCloseable { - Span.current().spanContext.spanIdAsHexString == applicationSpan.spanContext.spanIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.spanIdAsHexString == applicationSpan.spanContext.spanIdAsHexString - - def agentSpan = agentTracer.spanBuilder("test2").startSpan() - agentSpan.makeCurrent().withCloseable { - Span.current().spanContext.spanIdAsHexString == agentSpan.spanContext.spanIdAsHexString - Span.current().spanContext.traceIdAsHexString == agentSpan.spanContext.spanIdAsHexString - Span.current().spanContext.traceIdAsHexString == applicationSpan.spanContext.spanIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.spanIdAsHexString == agentSpan.spanContext.spanIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.traceIdAsHexString == agentSpan.spanContext.traceIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.traceIdAsHexString == applicationSpan.spanContext.traceIdAsHexString - - def applicationSpan2 = applicationTracer.spanBuilder("test3").startSpan() - applicationSpan2.makeCurrent().withCloseable { - Span.current().spanContext.spanIdAsHexString == applicationSpan2.spanContext.spanIdAsHexString - Span.current().spanContext.traceIdAsHexString == applicationSpan2.spanContext.spanIdAsHexString - Span.current().spanContext.traceIdAsHexString == applicationSpan.spanContext.spanIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.spanIdAsHexString == applicationSpan2.spanContext.spanIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.traceIdAsHexString == applicationSpan2.spanContext.traceIdAsHexString - io.opentelemetry.api.trace.Span.current().spanContext.traceIdAsHexString == applicationSpan.spanContext.traceIdAsHexString - } - } - } - } - - def "agent wraps"() { - expect: - def agentContext = io.opentelemetry.context.Context.current().with(COUNTRY, "japan") - agentContext.makeCurrent().withCloseable { - Context.current().with(ANIMAL, "cat").makeCurrent().withCloseable { - io.opentelemetry.context.Context.current().get(COUNTRY) == "japan" - Context.current().get(ANIMAL) == "cat" - - def agentValue = new AtomicReference() - def applicationValue = new AtomicReference() - Runnable runnable = { - agentValue.set(io.opentelemetry.context.Context.current().get(COUNTRY)) - applicationValue.set(Context.current().get(ANIMAL)) - } - - runnable.run() - agentValue.get() == null - applicationValue.get() == null - - def ctx = io.opentelemetry.context.Context.current() - // Simulate another thread by remounting root - Context.root().makeCurrent().withCloseable { - io.opentelemetry.context.Context.root().makeCurrent().withCloseable { - ctx.wrap(runnable).run() - } - } - agentValue.get() == "japan" - applicationValue.get() == "cat" - } - } - } - - def "application wraps"() { - expect: - def agentContext = io.opentelemetry.context.Context.current().with(COUNTRY, "japan") - agentContext.makeCurrent().withCloseable { - Context.current().with(ANIMAL, "cat").makeCurrent().withCloseable { - io.opentelemetry.context.Context.current().get(COUNTRY) == "japan" - Context.current().get(ANIMAL) == "cat" - - def agentValue = new AtomicReference() - def applicationValue = new AtomicReference() - Runnable runnable = { - agentValue.set(io.opentelemetry.context.Context.current().get(COUNTRY)) - applicationValue.set(Context.current().get(ANIMAL)) - } - - agentValue.get() == null - applicationValue.get() == null - - def ctx = Context.current() - // Simulate another thread by remounting root - Context.root().makeCurrent().withCloseable { - io.opentelemetry.context.Context.root().makeCurrent().withCloseable { - ctx.wrap(runnable).run() - } - } - agentValue.get() == "japan" - applicationValue.get() == "cat" - } - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/test/groovy/ContextTest.groovy b/instrumentation/opentelemetry-api-1.0/src/test/groovy/ContextTest.groovy deleted file mode 100644 index 7e2c8fe83b..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/test/groovy/ContextTest.groovy +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import application.io.opentelemetry.api.OpenTelemetry -import application.io.opentelemetry.api.trace.Span -import application.io.opentelemetry.context.Context -import io.opentelemetry.instrumentation.test.AgentTestRunner - -class ContextTest extends AgentTestRunner { - - def "Span.current() should return invalid"() { - when: - def span = Span.current() - - then: - !span.spanContext.valid - } - - def "Span.current() should return span"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - def scope = testSpan.makeCurrent() - def span = Span.current() - scope.close() - - then: - span == testSpan - } - - def "Span.fromContext should return invalid"() { - when: - def span = Span.fromContext(Context.current()) - - then: - !span.spanContext.valid - } - - def "getSpan should return span"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - def scope = testSpan.makeCurrent() - def span = Span.fromContext(Context.current()) - scope.close() - - then: - span == testSpan - } - - def "Span.fromContextOrNull should return null"() { - when: - def span = Span.fromContextOrNull(Context.current()) - - then: - span == null - } - - def "Span.fromContextOrNull should return span"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - def scope = testSpan.makeCurrent() - def span = Span.fromContextOrNull(Context.current()) - scope.close() - - then: - span == testSpan - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/test/groovy/MeterTest.groovy b/instrumentation/opentelemetry-api-1.0/src/test/groovy/MeterTest.groovy deleted file mode 100644 index 27f47af509..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/test/groovy/MeterTest.groovy +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.GAUGE_DOUBLE -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.GAUGE_LONG -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.MONOTONIC_DOUBLE -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.MONOTONIC_LONG -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.NON_MONOTONIC_DOUBLE -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.NON_MONOTONIC_LONG -import static io.opentelemetry.sdk.metrics.data.MetricData.Type.SUMMARY - -import application.io.opentelemetry.api.OpenTelemetry -import application.io.opentelemetry.api.common.Labels -import application.io.opentelemetry.api.metrics.AsynchronousInstrument -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.sdk.OpenTelemetrySdk -import io.opentelemetry.sdk.metrics.data.MetricData - -class MeterTest extends AgentTestRunner { - - def "test counter #builderMethod bound=#bind"() { - given: - // meters are global, and no way to unregister them, so tests use random name to avoid each other - def instrumentationName = "test" + new Random().nextLong() - - when: - def meter = OpenTelemetry.getGlobalMeterProvider().get(instrumentationName, "1.2.3") - def instrument = meter."$builderMethod"("test") - .setDescription("d") - .setUnit("u") - .build() - if (bind) { - instrument = instrument.bind(Labels.empty()) - } - if (bind) { - instrument.add(value1) - instrument.add(value2) - } else { - instrument.add(value1, Labels.of("q", "r")) - instrument.add(value2, Labels.of("q", "r")) - } - - then: - def metricData = findMetric(OpenTelemetrySdk.getGlobalMeterProvider().getMetricProducer().collectAllMetrics(), instrumentationName, "test") - metricData != null - metricData.description == "d" - metricData.unit == "u" - metricData.type == expectedType - metricData.instrumentationLibraryInfo.name == instrumentationName - metricData.instrumentationLibraryInfo.version == "1.2.3" - metricData.points.size() == 1 - def point = metricData.points.iterator().next() - if (bind) { - point.labels == io.opentelemetry.api.common.Labels.of("w", "x", "y", "z") - } else { - point.labels == io.opentelemetry.api.common.Labels.of("q", "r") - } - point.value == expectedValue - - where: - builderMethod | bind | value1 | value2 | expectedValue | expectedType - "longCounterBuilder" | false | 5 | 6 | 11 | MONOTONIC_LONG - "longCounterBuilder" | true | 5 | 6 | 11 | MONOTONIC_LONG - "longUpDownCounterBuilder" | false | 5 | 6 | 11 | NON_MONOTONIC_LONG - "longUpDownCounterBuilder" | true | 5 | 6 | 11 | NON_MONOTONIC_LONG - "doubleCounterBuilder" | false | 5.5 | 6.6 | 12.1 | MONOTONIC_DOUBLE - "doubleCounterBuilder" | true | 5.5 | 6.6 | 12.1 | MONOTONIC_DOUBLE - "doubleUpDownCounterBuilder" | false | 5.5 | 6.6 | 12.1 | NON_MONOTONIC_DOUBLE - "doubleUpDownCounterBuilder" | true | 5.5 | 6.6 | 12.1 | NON_MONOTONIC_DOUBLE - } - - def "test recorder #builderMethod bound=#bind"() { - given: - // meters are global, and no way to unregister them, so tests use random name to avoid each other - def instrumentationName = "test" + new Random().nextLong() - - when: - def meter = OpenTelemetry.getGlobalMeterProvider().get(instrumentationName, "1.2.3") - def instrument = meter."$builderMethod"("test") - .setDescription("d") - .setUnit("u") - .build() - if (bind) { - instrument = instrument.bind(Labels.empty()) - } - if (bind) { - instrument.record(value1) - instrument.record(value2) - } else { - instrument.record(value1, Labels.of("q", "r")) - instrument.record(value2, Labels.of("q", "r")) - } - - then: - def metricData = findMetric(OpenTelemetrySdk.getGlobalMeterProvider().getMetricProducer().collectAllMetrics(), instrumentationName, "test") - metricData != null - metricData.description == "d" - metricData.unit == "u" - metricData.type == SUMMARY - metricData.instrumentationLibraryInfo.name == instrumentationName - metricData.instrumentationLibraryInfo.version == "1.2.3" - metricData.points.size() == 1 - def point = metricData.points.iterator().next() - if (bind) { - point.labels == io.opentelemetry.api.common.Labels.of("w", "x", "y", "z") - } else { - point.labels == io.opentelemetry.api.common.Labels.of("q", "r") - } - - where: - builderMethod | bind | value1 | value2 | sum - "longValueRecorderBuilder" | false | 5 | 6 | 11 - "longValueRecorderBuilder" | true | 5 | 6 | 11 - "doubleValueRecorderBuilder" | false | 5.5 | 6.6 | 12.1 - "doubleValueRecorderBuilder" | true | 5.5 | 6.6 | 12.1 - } - - def "test observer #builderMethod"() { - given: - // meters are global, and no way to unregister them, so tests use random name to avoid each other - def instrumentationName = "test" + new Random().nextLong() - - when: - def meter = OpenTelemetry.getGlobalMeterProvider().get(instrumentationName, "1.2.3") - def instrument = meter."$builderMethod"("test") - .setDescription("d") - .setUnit("u") - .build() - if (builderMethod == "longSumObserverBuilder") { - instrument.setCallback(new AsynchronousInstrument.Callback() { - @Override - void update(AsynchronousInstrument.LongResult resultLongSumObserver) { - resultLongSumObserver.observe(123, Labels.of("q", "r")) - } - }) - } else if (builderMethod == "longUpDownSumObserverBuilder") { - instrument.setCallback(new AsynchronousInstrument.Callback() { - @Override - void update(AsynchronousInstrument.LongResult resultLongUpDownSumObserver) { - resultLongUpDownSumObserver.observe(123, Labels.of("q", "r")) - } - }) - } else if (builderMethod == "longValueObserverBuilder") { - instrument.setCallback(new AsynchronousInstrument.Callback() { - @Override - void update(AsynchronousInstrument.LongResult resultLongObserver) { - resultLongObserver.observe(123, Labels.of("q", "r")) - } - }) - } else if (builderMethod == "doubleSumObserverBuilder") { - instrument.setCallback(new AsynchronousInstrument.Callback() { - @Override - void update(AsynchronousInstrument.DoubleResult resultDoubleSumObserver) { - resultDoubleSumObserver.observe(1.23, Labels.of("q", "r")) - } - }) - } else if (builderMethod == "doubleUpDownSumObserverBuilder") { - instrument.setCallback(new AsynchronousInstrument.Callback() { - @Override - void update(AsynchronousInstrument.DoubleResult resultDoubleUpDownSumObserver) { - resultDoubleUpDownSumObserver.observe(1.23, Labels.of("q", "r")) - } - }) - } else if (builderMethod == "doubleValueObserverBuilder") { - instrument.setCallback(new AsynchronousInstrument.Callback() { - @Override - void update(AsynchronousInstrument.DoubleResult resultDoubleObserver) { - resultDoubleObserver.observe(1.23, Labels.of("q", "r")) - } - }) - } - - then: - def metricData = findMetric(OpenTelemetrySdk.getGlobalMeterProvider().getMetricProducer().collectAllMetrics(), instrumentationName, "test") - metricData != null - metricData.description == "d" - metricData.unit == "u" - metricData.type == expectedType - metricData.instrumentationLibraryInfo.name == instrumentationName - metricData.instrumentationLibraryInfo.version == "1.2.3" - metricData.points.size() == 1 - def point = metricData.points.iterator().next() - point.labels == io.opentelemetry.api.common.Labels.of("q", "r") - if (builderMethod.startsWith("long")) { - point.value == 123 - } else { - point.value == 1.23 - } - - where: - builderMethod | valueMethod | expectedType - "longSumObserverBuilder" | "value" | MONOTONIC_LONG - "longUpDownSumObserverBuilder" | "value" | NON_MONOTONIC_LONG - "longValueObserverBuilder" | "sum" | GAUGE_LONG - "doubleSumObserverBuilder" | "value" | MONOTONIC_DOUBLE - "doubleUpDownSumObserverBuilder" | "value" | NON_MONOTONIC_DOUBLE - "doubleValueObserverBuilder" | "sum" | GAUGE_DOUBLE - } - - def "test batch recorder"() { - given: - // meters are global, and no way to unregister them, so tests use random name to avoid each other - def instrumentationName = "test" + new Random().nextLong() - - when: - def meter = OpenTelemetry.getGlobalMeterProvider().get(instrumentationName, "1.2.3") - def longCounter = meter.longCounterBuilder("test") - .setDescription("d") - .setUnit("u") - .build() - def doubleMeasure = meter.doubleValueRecorderBuilder("test2") - .setDescription("d") - .setUnit("u") - .build() - - meter.newBatchRecorder("q", "r") - .put(longCounter, 5) - .put(longCounter, 6) - .put(doubleMeasure, 5.5) - .put(doubleMeasure, 6.6) - .record() - - def allMetrics = OpenTelemetrySdk.getGlobalMeterProvider().getMetricProducer().collectAllMetrics() - - then: - def metricData = findMetric(allMetrics, instrumentationName, "test") - metricData != null - metricData.description == "d" - metricData.unit == "u" - metricData.type == MONOTONIC_LONG - metricData.instrumentationLibraryInfo.name == instrumentationName - metricData.instrumentationLibraryInfo.version == "1.2.3" - metricData.points.size() == 1 - def point = metricData.points.iterator().next() - point.labels == io.opentelemetry.api.common.Labels.of("q", "r") - point.value == 11 - - def metricData2 = findMetric(allMetrics, instrumentationName, "test2") - metricData2 != null - metricData2.description == "d" - metricData2.unit == "u" - metricData2.type == SUMMARY - metricData2.instrumentationLibraryInfo.name == instrumentationName - metricData2.instrumentationLibraryInfo.version == "1.2.3" - metricData2.points.size() == 1 - def point2 = metricData2.points.iterator().next() - point2.labels == io.opentelemetry.api.common.Labels.of("q", "r") - point2.count == 2 - point2.sum == 12.1 - } - - def findMetric(Collection allMetrics, instrumentationName, metricName) { - for (def metric : allMetrics) { - if (metric.instrumentationLibraryInfo.name == instrumentationName && metric.name == metricName) { - return metric - } - } - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/test/groovy/TracerSdkTest.groovy b/instrumentation/opentelemetry-api-1.0/src/test/groovy/TracerSdkTest.groovy deleted file mode 100644 index f232c98f74..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/test/groovy/TracerSdkTest.groovy +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import application.io.opentelemetry.sdk.OpenTelemetrySdk -import application.io.opentelemetry.sdk.trace.TracerSdkProvider -import io.opentelemetry.instrumentation.test.AgentTestRunner - -class TracerSdkTest extends AgentTestRunner { - - def "direct access to sdk should not fail"() { - when: - def provider = OpenTelemetrySdk.getGlobalTracerManagement() - - then: - provider instanceof TracerSdkProvider - } -} diff --git a/instrumentation/opentelemetry-api-1.0/src/test/groovy/TracerTest.groovy b/instrumentation/opentelemetry-api-1.0/src/test/groovy/TracerTest.groovy deleted file mode 100644 index 3a22b739df..0000000000 --- a/instrumentation/opentelemetry-api-1.0/src/test/groovy/TracerTest.groovy +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static application.io.opentelemetry.api.trace.Span.Kind.PRODUCER - -import application.io.opentelemetry.api.OpenTelemetry -import application.io.opentelemetry.api.common.Attributes -import application.io.opentelemetry.api.trace.Span -import application.io.opentelemetry.api.trace.StatusCode -import application.io.opentelemetry.context.Context -import application.io.opentelemetry.context.Scope -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner - -class TracerTest extends AgentTestRunner { - - def "capture span, kind, attributes, and status"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").setSpanKind(PRODUCER).startSpan() - testSpan.setAttribute("string", "1") - testSpan.setAttribute("long", 2) - testSpan.setAttribute("double", 3.0) - testSpan.setAttribute("boolean", true) - testSpan.setStatus(StatusCode.ERROR) - testSpan.end() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test" - kind io.opentelemetry.api.trace.Span.Kind.PRODUCER - hasNoParent() - status io.opentelemetry.api.trace.StatusCode.ERROR - attributes { - "string" "1" - "long" 2 - "double" 3.0 - "boolean" true - } - } - } - } - } - - def "capture span with implicit parent using Tracer.withSpan()"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - Span parentSpan = tracer.spanBuilder("parent").startSpan() - Scope parentScope = Context.current().with(parentSpan).makeCurrent() - - def testSpan = tracer.spanBuilder("test").startSpan() - testSpan.end() - - parentSpan.end() - parentScope.close() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - hasNoParent() - attributes { - } - } - span(1) { - name "test" - childOf span(0) - attributes { - } - } - } - } - } - - def "capture span with implicit parent using makeCurrent"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - Span parentSpan = tracer.spanBuilder("parent").startSpan() - Scope parentScope = parentSpan.makeCurrent() - - def testSpan = tracer.spanBuilder("test").startSpan() - testSpan.end() - - parentSpan.end() - parentScope.close() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - hasNoParent() - attributes { - } - } - span(1) { - name "test" - childOf span(0) - attributes { - } - } - } - } - } - - def "capture span with implicit parent using TracingContextUtils.withSpan and makeCurrent"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - Span parentSpan = tracer.spanBuilder("parent").startSpan() - def parentContext = Context.current().with(parentSpan) - Scope parentScope = parentContext.makeCurrent() - - def testSpan = tracer.spanBuilder("test").startSpan() - testSpan.end() - - parentSpan.end() - parentScope.close() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - hasNoParent() - attributes { - } - } - span(1) { - name "test" - childOf span(0) - attributes { - } - } - } - } - } - - def "capture span with explicit parent"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def parentSpan = tracer.spanBuilder("parent").startSpan() - def context = Context.root().with(parentSpan) - def testSpan = tracer.spanBuilder("test").setParent(context).startSpan() - testSpan.end() - parentSpan.end() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - hasNoParent() - attributes { - } - } - span(1) { - name "test" - childOf span(0) - attributes { - } - } - } - } - } - - def "capture span with explicit no parent"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def parentSpan = tracer.spanBuilder("parent").startSpan() - def parentScope = parentSpan.makeCurrent() - def testSpan = tracer.spanBuilder("test").setNoParent().startSpan() - testSpan.end() - parentSpan.end() - parentScope.close() - - then: - assertTraces(2) { - trace(0, 1) { - span(0) { - name "parent" - hasNoParent() - attributes { - } - } - } - trace(1, 1) { - span(0) { - name "test" - hasNoParent() - attributes { - } - } - } - } - } - - def "capture name update"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - testSpan.updateName("test2") - testSpan.end() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test2" - hasNoParent() - attributes { - } - } - } - } - } - - def "capture exception()"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - testSpan.recordException(new IllegalStateException()) - testSpan.end() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test" - event(0) { - eventName("exception") - attributes { - "${SemanticAttributes.EXCEPTION_TYPE.key()}" "java.lang.IllegalStateException" - "${SemanticAttributes.EXCEPTION_STACKTRACE.key()}" String - } - } - attributes { - } - } - } - } - } - - def "capture exception with Attributes()"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - testSpan.recordException( - new IllegalStateException(), - Attributes.builder().put("dog", "bark").build()) - testSpan.end() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test" - event(0) { - eventName("exception") - attributes { - "${SemanticAttributes.EXCEPTION_TYPE.key()}" "java.lang.IllegalStateException" - "${SemanticAttributes.EXCEPTION_STACKTRACE.key()}" String - "dog" "bark" - } - } - attributes { - } - } - } - } - } - - def "capture name update using TracingContextUtils.getCurrentSpan()"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - def testScope = Context.current().with(testSpan).makeCurrent() - Span.current().updateName("test2") - testScope.close() - testSpan.end() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test2" - hasNoParent() - attributes { - } - } - } - } - } - - def "capture name update using TracingContextUtils.Span.fromContext(Context.current())"() { - when: - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").startSpan() - def testScope = Context.current().with(testSpan).makeCurrent() - Span.fromContext(Context.current()).updateName("test2") - testScope.close() - testSpan.end() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "test2" - hasNoParent() - attributes { - } - } - } - } - } - - def "add wrapped span to context"() { - when: - // Lazy way to get a span context - def tracer = OpenTelemetry.getGlobalTracer("test") - def testSpan = tracer.spanBuilder("test").setSpanKind(PRODUCER).startSpan() - testSpan.end() - - def span = Span.wrap(testSpan.getSpanContext()) - def context = Context.current().with(span) - - then: - Span.fromContext(context).getSpanContext().getSpanIdAsHexString() == span.getSpanContext().getSpanIdAsHexString() - } -} diff --git a/instrumentation/play-ws/play-ws-1.0/play-ws-1.0.gradle b/instrumentation/play-ws/play-ws-1.0/play-ws-1.0.gradle deleted file mode 100644 index 1d21a381d9..0000000000 --- a/instrumentation/play-ws/play-ws-1.0/play-ws-1.0.gradle +++ /dev/null @@ -1,38 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.11' - versions = '[1.0.0,2.0.0)' - assertInverse = true - } - pass { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.12' - versions = '[1.0.0,2.0.0)' - assertInverse = true - } - fail { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.13' - versions = '[,]' - } -} - -def scalaVersion = '2.12' - -dependencies { - library group: 'com.typesafe.play', name: "play-ahc-ws-standalone_$scalaVersion", version: '1.0.2' - - implementation project(':instrumentation:play-ws:play-ws-common') - - testImplementation project(':instrumentation:play-ws:play-ws-testing') - - // These are to ensure cross compatibility - testImplementation project(':instrumentation:netty:netty-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:akka-http-10.0') - - latestDepTestLibrary group: 'com.typesafe.play', name: "play-ahc-ws-standalone_$scalaVersion", version: '1.+' -} diff --git a/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/AsyncHandlerWrapper.java b/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/AsyncHandlerWrapper.java deleted file mode 100644 index effaa5a133..0000000000 --- a/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/AsyncHandlerWrapper.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v1_0; - -import static io.opentelemetry.javaagent.instrumentation.playws.PlayWsClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import play.shaded.ahc.org.asynchttpclient.AsyncHandler; -import play.shaded.ahc.org.asynchttpclient.HttpResponseBodyPart; -import play.shaded.ahc.org.asynchttpclient.HttpResponseHeaders; -import play.shaded.ahc.org.asynchttpclient.HttpResponseStatus; -import play.shaded.ahc.org.asynchttpclient.Response; - -public class AsyncHandlerWrapper implements AsyncHandler { - private final AsyncHandler delegate; - private final Span span; - private final Context invocationContext; - - private final Response.ResponseBuilder builder = new Response.ResponseBuilder(); - - public AsyncHandlerWrapper(AsyncHandler delegate, Span span, Context invocationContext) { - this.delegate = delegate; - this.span = span; - this.invocationContext = invocationContext; - } - - @Override - public State onBodyPartReceived(HttpResponseBodyPart content) throws Exception { - builder.accumulate(content); - return delegate.onBodyPartReceived(content); - } - - @Override - public State onStatusReceived(HttpResponseStatus status) throws Exception { - builder.reset(); - builder.accumulate(status); - return delegate.onStatusReceived(status); - } - - @Override - public State onHeadersReceived(HttpResponseHeaders httpHeaders) throws Exception { - builder.accumulate(httpHeaders); - return delegate.onHeadersReceived(httpHeaders); - } - - @Override - public Object onCompleted() throws Exception { - Response response = builder.build(); - tracer().end(span, response); - - try (Scope scope = invocationContext.makeCurrent()) { - return delegate.onCompleted(); - } - } - - @Override - public void onThrowable(Throwable throwable) { - tracer().endExceptionally(span, throwable); - span.end(); - - try (Scope scope = invocationContext.makeCurrent()) { - delegate.onThrowable(throwable); - } - } -} diff --git a/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/PlayWsInstrumentationModule.java b/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/PlayWsInstrumentationModule.java deleted file mode 100644 index 45e5d5414d..0000000000 --- a/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/PlayWsInstrumentationModule.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v1_0; - -import static io.opentelemetry.javaagent.instrumentation.playws.PlayWsClientTracer.tracer; -import static java.util.Collections.singletonList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.playws.AsyncHttpClientInstrumentation; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import net.bytebuddy.asm.Advice; -import play.shaded.ahc.org.asynchttpclient.AsyncHandler; -import play.shaded.ahc.org.asynchttpclient.Request; -import play.shaded.ahc.org.asynchttpclient.handler.StreamedAsyncHandler; -import play.shaded.ahc.org.asynchttpclient.ws.WebSocketUpgradeHandler; - -@AutoService(InstrumentationModule.class) -public class PlayWsInstrumentationModule extends InstrumentationModule { - public PlayWsInstrumentationModule() { - super("play-ws", "play-ws-1.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AsyncHttpClientInstrumentation(ClientAdvice.class.getName())); - } - - public static class ClientAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) Request request, - @Advice.Argument(value = 1, readOnly = false) AsyncHandler asyncHandler, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - Context parentContext = Java8BytecodeBridge.currentContext(); - - span = tracer().startSpan(request); - scope = tracer().startScope(span, request.getHeaders()); - - if (asyncHandler instanceof StreamedAsyncHandler) { - asyncHandler = - new StreamedAsyncHandlerWrapper( - (StreamedAsyncHandler) asyncHandler, span, parentContext); - } else if (!(asyncHandler instanceof WebSocketUpgradeHandler)) { - // websocket upgrade handlers aren't supported - asyncHandler = new AsyncHandlerWrapper(asyncHandler, span, parentContext); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/StreamedAsyncHandlerWrapper.java b/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/StreamedAsyncHandlerWrapper.java deleted file mode 100644 index c8953bff4b..0000000000 --- a/instrumentation/play-ws/play-ws-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v1_0/StreamedAsyncHandlerWrapper.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v1_0; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import org.reactivestreams.Publisher; -import play.shaded.ahc.org.asynchttpclient.handler.StreamedAsyncHandler; - -public class StreamedAsyncHandlerWrapper extends AsyncHandlerWrapper - implements StreamedAsyncHandler { - private final StreamedAsyncHandler streamedDelegate; - - public StreamedAsyncHandlerWrapper( - StreamedAsyncHandler delegate, Span span, Context invocationContext) { - super(delegate, span, invocationContext); - streamedDelegate = delegate; - } - - @Override - public State onStream(Publisher publisher) { - return streamedDelegate.onStream(publisher); - } -} diff --git a/instrumentation/play-ws/play-ws-1.0/src/test/groovy/PlayWsClientTest.groovy b/instrumentation/play-ws/play-ws-1.0/src/test/groovy/PlayWsClientTest.groovy deleted file mode 100644 index 7c094dd73a..0000000000 --- a/instrumentation/play-ws/play-ws-1.0/src/test/groovy/PlayWsClientTest.groovy +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.TimeUnit -import play.libs.ws.StandaloneWSClient -import play.libs.ws.StandaloneWSRequest -import play.libs.ws.StandaloneWSResponse -import play.libs.ws.ahc.StandaloneAhcWSClient -import scala.collection.JavaConverters -import scala.concurrent.Await -import scala.concurrent.ExecutionContext -import scala.concurrent.Future -import scala.concurrent.duration.Duration -import spock.lang.Shared - -class PlayJavaWsClientTest extends PlayWsClientTestBase { - @Shared - StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - StandaloneWSRequest wsRequest = wsClient.url(uri.toURL().toString()).setFollowRedirects(true) - - headers.entrySet().each { entry -> wsRequest.addHeader(entry.getKey(), entry.getValue()) } - StandaloneWSResponse wsResponse = wsRequest.setMethod(method).execute() - .whenComplete({ response, throwable -> - callback?.call() - }).toCompletableFuture().get(5, TimeUnit.SECONDS) - - return wsResponse.getStatus() - } - - def setupSpec() { - wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -class PlayJavaStreamedWsClientTest extends PlayWsClientTestBase { - @Shared - StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - StandaloneWSRequest wsRequest = wsClient.url(uri.toURL().toString()).setFollowRedirects(true) - - headers.entrySet().each { entry -> wsRequest.addHeader(entry.getKey(), entry.getValue()) } - StandaloneWSResponse wsResponse = wsRequest.setMethod(method).stream() - .whenComplete({ response, throwable -> - callback?.call() - }).toCompletableFuture().get(5, TimeUnit.SECONDS) - - // The status can be ready before the body so explicity call wait for body to be ready - wsResponse.getBodyAsSource().runFold("", { acc, out -> "" }, materializer) - .toCompletableFuture().get(5, TimeUnit.SECONDS) - return wsResponse.getStatus() - } - - def setupSpec() { - wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -class PlayScalaWsClientTest extends PlayWsClientTestBase { - @Shared - play.api.libs.ws.StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Future futureResponse = wsClient.url(uri.toURL().toString()) - .withMethod(method) - .withFollowRedirects(true) - .withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq()) - .execute() - .transform({ theTry -> - callback?.call() - theTry - }, ExecutionContext.global()) - - play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - - return wsResponse.status() - } - - def setupSpec() { - wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -class PlayScalaStreamedWsClientTest extends PlayWsClientTestBase { - @Shared - play.api.libs.ws.StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Future futureResponse = wsClient.url(uri.toURL().toString()) - .withMethod(method) - .withFollowRedirects(true) - .withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq()) - .stream() - .transform({ theTry -> - callback?.call() - theTry - }, ExecutionContext.global()) - - play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - - // The status can be ready before the body so explicity call wait for body to be ready - Await.result( - wsResponse.bodyAsSource().runFold("", { acc, out -> "" }, materializer), - Duration.apply(5, TimeUnit.SECONDS)) - return wsResponse.status() - } - - def setupSpec() { - wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} diff --git a/instrumentation/play-ws/play-ws-2.0/play-ws-2.0.gradle b/instrumentation/play-ws/play-ws-2.0/play-ws-2.0.gradle deleted file mode 100644 index 4a5f8a8980..0000000000 --- a/instrumentation/play-ws/play-ws-2.0/play-ws-2.0.gradle +++ /dev/null @@ -1,43 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - - pass { - module = 'play-ahc-ws-standalone_2.11' - group = 'com.typesafe.play' - versions = '[2.0.0,]' - assertInverse = true - } - - pass { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.12' - versions = '[2.0.0,2.1.0)' - skipVersions += '2.0.5' // Bad release - assertInverse = true - } - - // No Scala 2.13 versions below 2.0.6 exist - pass { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.13' - versions = '[2.0.6,2.1.0)' - } -} - -def scalaVersion = '2.12' - -dependencies { - library group: 'com.typesafe.play', name: "play-ahc-ws-standalone_$scalaVersion", version: '2.0.0' - - implementation project(':instrumentation:play-ws:play-ws-common') - - testImplementation project(':instrumentation:play-ws:play-ws-testing') - - // These are to ensure cross compatibility - testImplementation project(':instrumentation:netty:netty-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:akka-http-10.0') - - latestDepTestLibrary group: 'com.typesafe.play', name: "play-ahc-ws-standalone_$scalaVersion", version: '2.0.+' -} diff --git a/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/AsyncHandlerWrapper.java b/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/AsyncHandlerWrapper.java deleted file mode 100644 index b0422cc93a..0000000000 --- a/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/AsyncHandlerWrapper.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.playws.PlayWsClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import java.net.InetSocketAddress; -import java.util.List; -import play.shaded.ahc.io.netty.channel.Channel; -import play.shaded.ahc.io.netty.handler.codec.http.HttpHeaders; -import play.shaded.ahc.org.asynchttpclient.AsyncHandler; -import play.shaded.ahc.org.asynchttpclient.HttpResponseBodyPart; -import play.shaded.ahc.org.asynchttpclient.HttpResponseStatus; -import play.shaded.ahc.org.asynchttpclient.Response; -import play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequest; - -public class AsyncHandlerWrapper implements AsyncHandler { - private final AsyncHandler delegate; - private final Span span; - private final Context parentContext; - - private final Response.ResponseBuilder builder = new Response.ResponseBuilder(); - - public AsyncHandlerWrapper(AsyncHandler delegate, Span span) { - this.delegate = delegate; - this.span = span; - parentContext = Context.current(); - } - - @Override - public State onBodyPartReceived(HttpResponseBodyPart content) throws Exception { - builder.accumulate(content); - return delegate.onBodyPartReceived(content); - } - - @Override - public State onStatusReceived(HttpResponseStatus status) throws Exception { - builder.reset(); - builder.accumulate(status); - return delegate.onStatusReceived(status); - } - - @Override - public State onHeadersReceived(HttpHeaders httpHeaders) throws Exception { - builder.accumulate(httpHeaders); - return delegate.onHeadersReceived(httpHeaders); - } - - @Override - public Object onCompleted() throws Exception { - Response response = builder.build(); - tracer().end(span, response); - - try (Scope ignored = parentContext.makeCurrent()) { - return delegate.onCompleted(); - } - } - - @Override - public void onThrowable(Throwable throwable) { - tracer().endExceptionally(span, throwable); - - try (Scope ignored = parentContext.makeCurrent()) { - delegate.onThrowable(throwable); - } - } - - @Override - public State onTrailingHeadersReceived(HttpHeaders headers) throws Exception { - return delegate.onTrailingHeadersReceived(headers); - } - - @Override - public void onHostnameResolutionAttempt(String name) { - delegate.onHostnameResolutionAttempt(name); - } - - @Override - public void onHostnameResolutionSuccess(String name, List list) { - delegate.onHostnameResolutionSuccess(name, list); - } - - @Override - public void onHostnameResolutionFailure(String name, Throwable cause) { - delegate.onHostnameResolutionFailure(name, cause); - } - - @Override - public void onTcpConnectAttempt(InetSocketAddress remoteAddress) { - delegate.onTcpConnectAttempt(remoteAddress); - } - - @Override - public void onTcpConnectSuccess(InetSocketAddress remoteAddress, Channel connection) { - delegate.onTcpConnectSuccess(remoteAddress, connection); - } - - @Override - public void onTcpConnectFailure(InetSocketAddress remoteAddress, Throwable cause) { - delegate.onTcpConnectFailure(remoteAddress, cause); - } - - @Override - public void onTlsHandshakeAttempt() { - delegate.onTlsHandshakeAttempt(); - } - - @Override - public void onTlsHandshakeSuccess() { - delegate.onTlsHandshakeSuccess(); - } - - @Override - public void onTlsHandshakeFailure(Throwable cause) { - delegate.onTlsHandshakeFailure(cause); - } - - @Override - public void onConnectionPoolAttempt() { - delegate.onConnectionPoolAttempt(); - } - - @Override - public void onConnectionPooled(Channel connection) { - delegate.onConnectionPooled(connection); - } - - @Override - public void onConnectionOffer(Channel connection) { - delegate.onConnectionOffer(connection); - } - - @Override - public void onRequestSend(NettyRequest request) { - delegate.onRequestSend(request); - } - - @Override - public void onRetry() { - delegate.onRetry(); - } -} diff --git a/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/PlayWsInstrumentationModule.java b/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/PlayWsInstrumentationModule.java deleted file mode 100644 index 1fa9ebb209..0000000000 --- a/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/PlayWsInstrumentationModule.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v2_0; - -import static io.opentelemetry.javaagent.instrumentation.playws.PlayWsClientTracer.tracer; -import static java.util.Collections.singletonList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.playws.AsyncHttpClientInstrumentation; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import net.bytebuddy.asm.Advice; -import play.shaded.ahc.org.asynchttpclient.AsyncHandler; -import play.shaded.ahc.org.asynchttpclient.Request; -import play.shaded.ahc.org.asynchttpclient.handler.StreamedAsyncHandler; -import play.shaded.ahc.org.asynchttpclient.ws.WebSocketUpgradeHandler; - -@AutoService(InstrumentationModule.class) -public class PlayWsInstrumentationModule extends InstrumentationModule { - public PlayWsInstrumentationModule() { - super("play-ws", "play-ws-2.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AsyncHttpClientInstrumentation(ClientAdvice.class.getName())); - } - - public static class ClientAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) Request request, - @Advice.Argument(value = 1, readOnly = false) AsyncHandler asyncHandler, - @Advice.Local("otelSpan") Span span) { - - span = tracer().startSpan(request); - // TODO (trask) expose inject separate from startScope, e.g. for async cases - Scope scope = tracer().startScope(span, request.getHeaders()); - scope.close(); - - if (asyncHandler instanceof StreamedAsyncHandler) { - asyncHandler = - new StreamedAsyncHandlerWrapper((StreamedAsyncHandler) asyncHandler, span); - } else if (!(asyncHandler instanceof WebSocketUpgradeHandler)) { - // websocket upgrade handlers aren't supported - asyncHandler = new AsyncHandlerWrapper(asyncHandler, span); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Thrown Throwable throwable, @Advice.Local("otelSpan") Span span) { - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/StreamedAsyncHandlerWrapper.java b/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/StreamedAsyncHandlerWrapper.java deleted file mode 100644 index 1963e3af98..0000000000 --- a/instrumentation/play-ws/play-ws-2.0/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_0/StreamedAsyncHandlerWrapper.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v2_0; - -import io.opentelemetry.api.trace.Span; -import org.reactivestreams.Publisher; -import play.shaded.ahc.org.asynchttpclient.handler.StreamedAsyncHandler; - -public class StreamedAsyncHandlerWrapper extends AsyncHandlerWrapper - implements StreamedAsyncHandler { - private final StreamedAsyncHandler streamedDelegate; - - public StreamedAsyncHandlerWrapper(StreamedAsyncHandler delegate, Span span) { - super(delegate, span); - streamedDelegate = delegate; - } - - @Override - public State onStream(Publisher publisher) { - return streamedDelegate.onStream(publisher); - } -} diff --git a/instrumentation/play-ws/play-ws-2.0/src/test/groovy/PlayWsClientTest.groovy b/instrumentation/play-ws/play-ws-2.0/src/test/groovy/PlayWsClientTest.groovy deleted file mode 100644 index 908cd50bb0..0000000000 --- a/instrumentation/play-ws/play-ws-2.0/src/test/groovy/PlayWsClientTest.groovy +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.TimeUnit -import play.libs.ws.StandaloneWSClient -import play.libs.ws.StandaloneWSRequest -import play.libs.ws.StandaloneWSResponse -import play.libs.ws.ahc.StandaloneAhcWSClient -import scala.collection.JavaConverters -import scala.concurrent.Await -import scala.concurrent.ExecutionContext -import scala.concurrent.Future -import scala.concurrent.duration.Duration -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class PlayJavaWsClientTest extends PlayWsClientTestBase { - @Shared - StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - StandaloneWSRequest wsRequest = wsClient.url(uri.toURL().toString()).setFollowRedirects(true) - - headers.entrySet().each { entry -> wsRequest.addHeader(entry.getKey(), entry.getValue()) } - StandaloneWSResponse wsResponse = wsRequest.setMethod(method).execute() - .whenComplete({ response, throwable -> - callback?.call() - }).toCompletableFuture().get(5, TimeUnit.SECONDS) - - return wsResponse.getStatus() - } - - def setupSpec() { - wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -@Timeout(5) -class PlayJavaStreamedWsClientTest extends PlayWsClientTestBase { - @Shared - StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - StandaloneWSRequest wsRequest = wsClient.url(uri.toURL().toString()).setFollowRedirects(true) - - headers.entrySet().each { entry -> wsRequest.addHeader(entry.getKey(), entry.getValue()) } - StandaloneWSResponse wsResponse = wsRequest.setMethod(method).stream() - .whenComplete({ response, throwable -> - callback?.call() - }).toCompletableFuture().get(5, TimeUnit.SECONDS) - - // The status can be ready before the body so explicity call wait for body to be ready - wsResponse.getBodyAsSource().runFold("", { acc, out -> "" }, materializer) - .toCompletableFuture().get(5, TimeUnit.SECONDS) - return wsResponse.getStatus() - } - - def setupSpec() { - wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -@Timeout(5) -class PlayScalaWsClientTest extends PlayWsClientTestBase { - @Shared - play.api.libs.ws.StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Future futureResponse = wsClient.url(uri.toURL().toString()) - .withMethod(method) - .withFollowRedirects(true) - .withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq()) - .execute() - .transform({ theTry -> - callback?.call() - theTry - }, ExecutionContext.global()) - - play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - - return wsResponse.status() - } - - def setupSpec() { - wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -@Timeout(5) -class PlayScalaStreamedWsClientTest extends PlayWsClientTestBase { - @Shared - play.api.libs.ws.StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Future futureResponse = wsClient.url(uri.toURL().toString()) - .withMethod(method) - .withFollowRedirects(true) - .withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq()) - .stream() - .transform({ theTry -> - callback?.call() - theTry - }, ExecutionContext.global()) - - play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - - // The status can be ready before the body so explicity call wait for body to be ready - Await.result( - wsResponse.bodyAsSource().runFold("", { acc, out -> "" }, materializer), - Duration.apply(5, TimeUnit.SECONDS)) - return wsResponse.status() - } - - def setupSpec() { - wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} diff --git a/instrumentation/play-ws/play-ws-2.1/play-ws-2.1.gradle b/instrumentation/play-ws/play-ws-2.1/play-ws-2.1.gradle deleted file mode 100644 index 850bb852fe..0000000000 --- a/instrumentation/play-ws/play-ws-2.1/play-ws-2.1.gradle +++ /dev/null @@ -1,41 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - - fail { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.11' - versions = '[,]' - } - - pass { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.12' - versions = '[2.1.0,]' - skipVersions += '2.0.5' // Bad release - assertInverse = true - } - - pass { - group = 'com.typesafe.play' - module = 'play-ahc-ws-standalone_2.13' - versions = '[2.1.0,]' - skipVersions += '2.0.5' // Bad release - assertInverse = true - } -} - -def scalaVersion = '2.12' - -dependencies { - library group: 'com.typesafe.play', name: "play-ahc-ws-standalone_$scalaVersion", version: '2.1.0' - - implementation project(':instrumentation:play-ws:play-ws-common') - - testImplementation project(':instrumentation:play-ws:play-ws-testing') - - // These are to ensure cross compatibility - testImplementation project(':instrumentation:netty:netty-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:akka-http-10.0') -} diff --git a/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/AsyncHandlerWrapper.java b/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/AsyncHandlerWrapper.java deleted file mode 100644 index e3bf596988..0000000000 --- a/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/AsyncHandlerWrapper.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v2_1; - -import static io.opentelemetry.javaagent.instrumentation.playws.PlayWsClientTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import java.net.InetSocketAddress; -import java.util.List; -import javax.net.ssl.SSLSession; -import play.shaded.ahc.io.netty.channel.Channel; -import play.shaded.ahc.io.netty.handler.codec.http.HttpHeaders; -import play.shaded.ahc.org.asynchttpclient.AsyncHandler; -import play.shaded.ahc.org.asynchttpclient.HttpResponseBodyPart; -import play.shaded.ahc.org.asynchttpclient.HttpResponseStatus; -import play.shaded.ahc.org.asynchttpclient.Response; -import play.shaded.ahc.org.asynchttpclient.netty.request.NettyRequest; - -public class AsyncHandlerWrapper implements AsyncHandler { - private final AsyncHandler delegate; - private final Span span; - private final Context parentContext; - - private final Response.ResponseBuilder builder = new Response.ResponseBuilder(); - - public AsyncHandlerWrapper(AsyncHandler delegate, Span span) { - this.delegate = delegate; - this.span = span; - parentContext = Context.current(); - } - - @Override - public State onBodyPartReceived(HttpResponseBodyPart content) throws Exception { - builder.accumulate(content); - return delegate.onBodyPartReceived(content); - } - - @Override - public State onStatusReceived(HttpResponseStatus status) throws Exception { - builder.reset(); - builder.accumulate(status); - return delegate.onStatusReceived(status); - } - - @Override - public State onHeadersReceived(HttpHeaders httpHeaders) throws Exception { - builder.accumulate(httpHeaders); - return delegate.onHeadersReceived(httpHeaders); - } - - @Override - public Object onCompleted() throws Exception { - Response response = builder.build(); - tracer().end(span, response); - - try (Scope ignored = parentContext.makeCurrent()) { - return delegate.onCompleted(); - } - } - - @Override - public void onThrowable(Throwable throwable) { - tracer().endExceptionally(span, throwable); - - try (Scope ignored = parentContext.makeCurrent()) { - delegate.onThrowable(throwable); - } - } - - @Override - public State onTrailingHeadersReceived(HttpHeaders headers) throws Exception { - return delegate.onTrailingHeadersReceived(headers); - } - - @Override - public void onHostnameResolutionAttempt(String name) { - delegate.onHostnameResolutionAttempt(name); - } - - @Override - public void onHostnameResolutionSuccess(String name, List list) { - delegate.onHostnameResolutionSuccess(name, list); - } - - @Override - public void onHostnameResolutionFailure(String name, Throwable cause) { - delegate.onHostnameResolutionFailure(name, cause); - } - - @Override - public void onTcpConnectAttempt(InetSocketAddress remoteAddress) { - delegate.onTcpConnectAttempt(remoteAddress); - } - - @Override - public void onTcpConnectSuccess(InetSocketAddress remoteAddress, Channel connection) { - delegate.onTcpConnectSuccess(remoteAddress, connection); - } - - @Override - public void onTcpConnectFailure(InetSocketAddress remoteAddress, Throwable cause) { - delegate.onTcpConnectFailure(remoteAddress, cause); - } - - @Override - public void onTlsHandshakeAttempt() { - delegate.onTlsHandshakeAttempt(); - } - - @Override - public void onTlsHandshakeSuccess(SSLSession sslSession) { - delegate.onTlsHandshakeSuccess(sslSession); - } - - @Override - public void onTlsHandshakeFailure(Throwable cause) { - delegate.onTlsHandshakeFailure(cause); - } - - @Override - public void onConnectionPoolAttempt() { - delegate.onConnectionPoolAttempt(); - } - - @Override - public void onConnectionPooled(Channel connection) { - delegate.onConnectionPooled(connection); - } - - @Override - public void onConnectionOffer(Channel connection) { - delegate.onConnectionOffer(connection); - } - - @Override - public void onRequestSend(NettyRequest request) { - delegate.onRequestSend(request); - } - - @Override - public void onRetry() { - delegate.onRetry(); - } -} diff --git a/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/PlayWsInstrumentationModule.java b/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/PlayWsInstrumentationModule.java deleted file mode 100644 index f86e5d9134..0000000000 --- a/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/PlayWsInstrumentationModule.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v2_1; - -import static io.opentelemetry.javaagent.instrumentation.playws.PlayWsClientTracer.tracer; -import static java.util.Collections.singletonList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.playws.AsyncHttpClientInstrumentation; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import net.bytebuddy.asm.Advice; -import play.shaded.ahc.org.asynchttpclient.AsyncHandler; -import play.shaded.ahc.org.asynchttpclient.Request; -import play.shaded.ahc.org.asynchttpclient.handler.StreamedAsyncHandler; -import play.shaded.ahc.org.asynchttpclient.ws.WebSocketUpgradeHandler; - -@AutoService(InstrumentationModule.class) -public class PlayWsInstrumentationModule extends InstrumentationModule { - public PlayWsInstrumentationModule() { - super("play-ws", "play-ws-2.1"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new AsyncHttpClientInstrumentation(ClientAdvice.class.getName())); - } - - public static class ClientAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(0) Request request, - @Advice.Argument(value = 1, readOnly = false) AsyncHandler asyncHandler, - @Advice.Local("otelSpan") Span span) { - - span = tracer().startSpan(request); - // TODO (trask) expose inject separate from startScope, e.g. for async cases - Scope scope = tracer().startScope(span, request.getHeaders()); - scope.close(); - - if (asyncHandler instanceof StreamedAsyncHandler) { - asyncHandler = - new StreamedAsyncHandlerWrapper((StreamedAsyncHandler) asyncHandler, span); - } else if (!(asyncHandler instanceof WebSocketUpgradeHandler)) { - // websocket upgrade handlers aren't supported - asyncHandler = new AsyncHandlerWrapper(asyncHandler, span); - } - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Thrown Throwable throwable, @Advice.Local("otelSpan") Span span) { - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } - } - } -} diff --git a/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/StreamedAsyncHandlerWrapper.java b/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/StreamedAsyncHandlerWrapper.java deleted file mode 100644 index 1f9190eb88..0000000000 --- a/instrumentation/play-ws/play-ws-2.1/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/v2_1/StreamedAsyncHandlerWrapper.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws.v2_1; - -import io.opentelemetry.api.trace.Span; -import org.reactivestreams.Publisher; -import play.shaded.ahc.org.asynchttpclient.handler.StreamedAsyncHandler; - -public class StreamedAsyncHandlerWrapper extends AsyncHandlerWrapper - implements StreamedAsyncHandler { - private final StreamedAsyncHandler streamedDelegate; - - public StreamedAsyncHandlerWrapper(StreamedAsyncHandler delegate, Span span) { - super(delegate, span); - streamedDelegate = delegate; - } - - @Override - public State onStream(Publisher publisher) { - return streamedDelegate.onStream(publisher); - } -} diff --git a/instrumentation/play-ws/play-ws-2.1/src/test/groovy/PlayWsClientTest.groovy b/instrumentation/play-ws/play-ws-2.1/src/test/groovy/PlayWsClientTest.groovy deleted file mode 100644 index 7c094dd73a..0000000000 --- a/instrumentation/play-ws/play-ws-2.1/src/test/groovy/PlayWsClientTest.groovy +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import java.util.concurrent.TimeUnit -import play.libs.ws.StandaloneWSClient -import play.libs.ws.StandaloneWSRequest -import play.libs.ws.StandaloneWSResponse -import play.libs.ws.ahc.StandaloneAhcWSClient -import scala.collection.JavaConverters -import scala.concurrent.Await -import scala.concurrent.ExecutionContext -import scala.concurrent.Future -import scala.concurrent.duration.Duration -import spock.lang.Shared - -class PlayJavaWsClientTest extends PlayWsClientTestBase { - @Shared - StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - StandaloneWSRequest wsRequest = wsClient.url(uri.toURL().toString()).setFollowRedirects(true) - - headers.entrySet().each { entry -> wsRequest.addHeader(entry.getKey(), entry.getValue()) } - StandaloneWSResponse wsResponse = wsRequest.setMethod(method).execute() - .whenComplete({ response, throwable -> - callback?.call() - }).toCompletableFuture().get(5, TimeUnit.SECONDS) - - return wsResponse.getStatus() - } - - def setupSpec() { - wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -class PlayJavaStreamedWsClientTest extends PlayWsClientTestBase { - @Shared - StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - StandaloneWSRequest wsRequest = wsClient.url(uri.toURL().toString()).setFollowRedirects(true) - - headers.entrySet().each { entry -> wsRequest.addHeader(entry.getKey(), entry.getValue()) } - StandaloneWSResponse wsResponse = wsRequest.setMethod(method).stream() - .whenComplete({ response, throwable -> - callback?.call() - }).toCompletableFuture().get(5, TimeUnit.SECONDS) - - // The status can be ready before the body so explicity call wait for body to be ready - wsResponse.getBodyAsSource().runFold("", { acc, out -> "" }, materializer) - .toCompletableFuture().get(5, TimeUnit.SECONDS) - return wsResponse.getStatus() - } - - def setupSpec() { - wsClient = new StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -class PlayScalaWsClientTest extends PlayWsClientTestBase { - @Shared - play.api.libs.ws.StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Future futureResponse = wsClient.url(uri.toURL().toString()) - .withMethod(method) - .withFollowRedirects(true) - .withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq()) - .execute() - .transform({ theTry -> - callback?.call() - theTry - }, ExecutionContext.global()) - - play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - - return wsResponse.status() - } - - def setupSpec() { - wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} - -class PlayScalaStreamedWsClientTest extends PlayWsClientTestBase { - @Shared - play.api.libs.ws.StandaloneWSClient wsClient - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - Future futureResponse = wsClient.url(uri.toURL().toString()) - .withMethod(method) - .withFollowRedirects(true) - .withHttpHeaders(JavaConverters.mapAsScalaMap(headers).toSeq()) - .stream() - .transform({ theTry -> - callback?.call() - theTry - }, ExecutionContext.global()) - - play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - - // The status can be ready before the body so explicity call wait for body to be ready - Await.result( - wsResponse.bodyAsSource().runFold("", { acc, out -> "" }, materializer), - Duration.apply(5, TimeUnit.SECONDS)) - return wsResponse.status() - } - - def setupSpec() { - wsClient = new play.api.libs.ws.ahc.StandaloneAhcWSClient(asyncHttpClient, materializer) - } - - def cleanupSpec() { - wsClient?.close() - } -} diff --git a/instrumentation/play-ws/play-ws-common/play-ws-common.gradle b/instrumentation/play-ws/play-ws-common/play-ws-common.gradle deleted file mode 100644 index ae13806563..0000000000 --- a/instrumentation/play-ws/play-ws-common/play-ws-common.gradle +++ /dev/null @@ -1,7 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -def scalaVersion = '2.12' - -dependencies { - compileOnly group: 'com.typesafe.play', name: "play-ahc-ws-standalone_$scalaVersion", version: '1.0.2' -} diff --git a/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/AsyncHttpClientInstrumentation.java b/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/AsyncHttpClientInstrumentation.java deleted file mode 100644 index c84f98d059..0000000000 --- a/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/AsyncHttpClientInstrumentation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class AsyncHttpClientInstrumentation implements TypeInstrumentation { - private final String adviceName; - - public AsyncHttpClientInstrumentation(String adviceName) { - this.adviceName = adviceName; - } - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("play.shaded.ahc.org.asynchttpclient.AsyncHttpClient"); - } - - @Override - public ElementMatcher typeMatcher() { - // CachingAsyncHttpClient rejects overrides to AsyncHandler - // It also delegates to another AsyncHttpClient - return nameStartsWith("play.") - .and( - implementsInterface(named("play.shaded.ahc.org.asynchttpclient.AsyncHttpClient")) - .and(not(named("play.api.libs.ws.ahc.cache.CachingAsyncHttpClient")))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("execute")) - .and(takesArguments(2)) - .and(takesArgument(0, named("play.shaded.ahc.org.asynchttpclient.Request"))) - .and(takesArgument(1, named("play.shaded.ahc.org.asynchttpclient.AsyncHandler"))), - adviceName); - } -} diff --git a/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/HeadersInjectAdapter.java b/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/HeadersInjectAdapter.java deleted file mode 100644 index c97081fcb4..0000000000 --- a/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/HeadersInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import play.shaded.ahc.io.netty.handler.codec.http.HttpHeaders; - -public class HeadersInjectAdapter implements TextMapPropagator.Setter { - - public static final HeadersInjectAdapter SETTER = new HeadersInjectAdapter(); - - @Override - public void set(HttpHeaders carrier, String key, String value) { - carrier.add(key, value); - } -} diff --git a/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientTracer.java b/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientTracer.java deleted file mode 100644 index e693dba988..0000000000 --- a/instrumentation/play-ws/play-ws-common/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientTracer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.playws; - -import static io.opentelemetry.javaagent.instrumentation.playws.HeadersInjectAdapter.SETTER; - -import io.opentelemetry.context.propagation.TextMapPropagator.Setter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import java.net.URI; -import java.net.URISyntaxException; -import play.shaded.ahc.io.netty.handler.codec.http.HttpHeaders; -import play.shaded.ahc.org.asynchttpclient.Request; -import play.shaded.ahc.org.asynchttpclient.Response; - -public class PlayWsClientTracer extends HttpClientTracer { - private static final PlayWsClientTracer TRACER = new PlayWsClientTracer(); - - public static PlayWsClientTracer tracer() { - return TRACER; - } - - @Override - protected String method(Request request) { - return request.getMethod(); - } - - @Override - protected URI url(Request request) throws URISyntaxException { - return request.getUri().toJavaNetURI(); - } - - @Override - protected Integer status(Response response) { - return response.getStatusCode(); - } - - @Override - protected String requestHeader(Request request, String name) { - return request.getHeaders().get(name); - } - - @Override - protected String responseHeader(Response response, String name) { - return response.getHeaders().get(name); - } - - @Override - protected Setter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.play-ws"; - } -} diff --git a/instrumentation/play/play-2.3/javaagent/src/test/groovy/server/PlayServerTest.groovy b/instrumentation/play/play-2.3/javaagent/src/test/groovy/server/PlayServerTest.groovy index bd8c61cc20..c6aee75842 100644 --- a/instrumentation/play/play-2.3/javaagent/src/test/groovy/server/PlayServerTest.groovy +++ b/instrumentation/play/play-2.3/javaagent/src/test/groovy/server/PlayServerTest.groovy @@ -5,9 +5,9 @@ package server +import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.base.HttpServerTest diff --git a/instrumentation/play/play-2.3/play-2.3.gradle b/instrumentation/play/play-2.3/play-2.3.gradle deleted file mode 100644 index 00db885cde..0000000000 --- a/instrumentation/play/play-2.3/play-2.3.gradle +++ /dev/null @@ -1,45 +0,0 @@ -ext { - // Play doesn't work with Java 9+ until 2.6.12 - maxJavaVersionForTests = JavaVersion.VERSION_1_8 -} - -apply from: "$rootDir/gradle/instrumentation.gradle" -apply from: "$rootDir/gradle/test-with-scala.gradle" - -muzzle { - pass { - group = 'com.typesafe.play' - module = 'play_2.11' - versions = '[2.3.0,2.4)' - assertInverse = true - } - fail { - group = 'com.typesafe.play' - module = 'play_2.12' - versions = '[,]' - } - fail { - group = 'com.typesafe.play' - module = 'play_2.13' - versions = '[,]' - } -} - -dependencies { - // TODO(anuraaga): Something about library configuration doesn't work well with scala compilation - // here. - compileOnly group: 'com.typesafe.play', name: 'play_2.11', version: '2.3.0' - - testImplementation project(':instrumentation:netty:netty-3.8') - - testLibrary group: 'com.typesafe.play', name: 'play-java-ws_2.11', version: '2.3.0' - testLibrary(group: 'com.typesafe.play', name: 'play-test_2.11', version: '2.3.0') { - exclude group: 'org.eclipse.jetty', module: 'jetty-websocket' - } - - latestDepTestLibrary group: 'com.typesafe.play', name: 'play-java_2.11', version: '2.3.+' - latestDepTestLibrary group: 'com.typesafe.play', name: 'play-java-ws_2.11', version: '2.3.+' - latestDepTestLibrary(group: 'com.typesafe.play', name: 'play-test_2.11', version: '2.3.+') { - exclude group: 'org.eclipse.jetty', module: 'jetty-websocket' - } -} diff --git a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayAdvice.java b/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayAdvice.java deleted file mode 100644 index 527bc6e2a4..0000000000 --- a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayAdvice.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_3; - -import static io.opentelemetry.javaagent.instrumentation.play.v2_3.PlayTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import net.bytebuddy.asm.Advice; -import play.api.mvc.Action; -import play.api.mvc.Headers; -import play.api.mvc.Request; -import play.api.mvc.Result; -import scala.concurrent.Future; - -public class PlayAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope onEnter(@Advice.Argument(0) final Request req) { - Span span = tracer().startSpan("play.request", Kind.INTERNAL); - - return new SpanWithScope(span, span.makeCurrent()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopTraceOnResponse( - @Advice.Enter SpanWithScope playControllerScope, - @Advice.This Object thisAction, - @Advice.Thrown Throwable throwable, - @Advice.Argument(0) Request req, - @Advice.Return(readOnly = false) Future responseFuture) { - Span playControllerSpan = playControllerScope.getSpan(); - - if (throwable == null) { - responseFuture.onComplete( - new RequestCompleteCallback(playControllerSpan), - ((Action) thisAction).executionContext()); - } else { - tracer().endExceptionally(playControllerSpan, throwable); - } - playControllerScope.closeScope(); - // span finished in RequestCompleteCallback - - // set the span name on the upstream akka/netty span - tracer().updateSpanName(BaseTracer.getCurrentServerSpan(), req); - } - - // With this muzzle prevents this instrumentation from applying on Play 2.4+ - public static void muzzleCheck(Headers headers) { - headers.get("aKey"); - } -} diff --git a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayInstrumentationModule.java b/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayInstrumentationModule.java deleted file mode 100644 index 2aba4273f0..0000000000 --- a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayInstrumentationModule.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_3; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class PlayInstrumentationModule extends InstrumentationModule { - - public PlayInstrumentationModule() { - super("play", "play-2.3"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ActionInstrumentation()); - } - - public static class ActionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("play.api.mvc.Action"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("play.api.mvc.Action")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("apply") - .and(takesArgument(0, named("play.api.mvc.Request"))) - .and(returns(named("scala.concurrent.Future"))), - PlayAdvice.class.getName()); - } - } -} diff --git a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayTracer.java b/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayTracer.java deleted file mode 100644 index 57982c2e1f..0000000000 --- a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/PlayTracer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_3; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.UndeclaredThrowableException; -import play.api.mvc.Request; -import scala.Option; - -public class PlayTracer extends BaseTracer { - private static final PlayTracer TRACER = new PlayTracer(); - - public static PlayTracer tracer() { - return TRACER; - } - - public Span updateSpanName(Span span, Request request) { - Option pathOption = request.tags().get("ROUTE_PATTERN"); - if (!pathOption.isEmpty()) { - String path = pathOption.get(); - span.updateName(path); - } - return span; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.play"; - } - - @Override - protected Throwable unwrapThrowable(Throwable throwable) { - // This can be moved to instanceof check when using Java 8. - if (throwable.getClass().getName().equals("java.util.concurrent.CompletionException") - && throwable.getCause() != null) { - throwable = throwable.getCause(); - } - while ((throwable instanceof InvocationTargetException - || throwable instanceof UndeclaredThrowableException) - && throwable.getCause() != null) { - throwable = throwable.getCause(); - } - return throwable; - } -} diff --git a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/RequestCompleteCallback.java b/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/RequestCompleteCallback.java deleted file mode 100644 index c56e65522d..0000000000 --- a/instrumentation/play/play-2.3/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_3/RequestCompleteCallback.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_3; - -import static io.opentelemetry.javaagent.instrumentation.play.v2_3.PlayTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import play.api.mvc.Result; -import scala.util.Try; - -public class RequestCompleteCallback extends scala.runtime.AbstractFunction1, Object> { - - private static final Logger log = LoggerFactory.getLogger(RequestCompleteCallback.class); - - private final Span span; - - public RequestCompleteCallback(Span span) { - this.span = span; - } - - @Override - public Object apply(Try result) { - try { - if (result.isFailure()) { - tracer().endExceptionally(span, result.failed().get()); - } else { - tracer().end(span); - } - } catch (Throwable t) { - log.debug("error in play instrumentation", t); - } - return null; - } -} diff --git a/instrumentation/play/play-2.3/src/test/groovy/client/PlayWsClientTest.groovy b/instrumentation/play/play-2.3/src/test/groovy/client/PlayWsClientTest.groovy deleted file mode 100644 index 874b3da30b..0000000000 --- a/instrumentation/play/play-2.3/src/test/groovy/client/PlayWsClientTest.groovy +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package client - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.util.concurrent.TimeUnit -import play.GlobalSettings -import play.libs.ws.WS -import play.test.FakeApplication -import play.test.Helpers -import spock.lang.Shared - -class PlayWsClientTest extends HttpClientTest { - @Shared - def application = new FakeApplication( - new File("."), - FakeApplication.getClassLoader(), - [ - "ws.timeout.connection": CONNECT_TIMEOUT_MS - ], - Collections.emptyList(), - new GlobalSettings() - ) - - @Shared - def client - - def setupSpec() { - Helpers.start(application) - client = WS.client() - } - - def cleanupSpec() { - Helpers.stop(application) - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = client.url(uri.toString()) - headers.entrySet().each { - request.setHeader(it.key, it.value) - } - - def status = request.execute(method).map({ - callback?.call() - it - }).map({ - it.status - }) - return status.get(1, TimeUnit.SECONDS) - } - - @Override - String userAgent() { - return "NING" - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - // On connection failures the operation and span names end up different from expected. - // This would require a lot of changes to the base client test class to support - // span.spanName = "netty.connect" - false - } -} diff --git a/instrumentation/play/play-2.3/src/test/groovy/server/PlayAsyncServerTest.groovy b/instrumentation/play/play-2.3/src/test/groovy/server/PlayAsyncServerTest.groovy deleted file mode 100644 index d17720db1f..0000000000 --- a/instrumentation/play/play-2.3/src/test/groovy/server/PlayAsyncServerTest.groovy +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import play.api.test.TestServer - -class PlayAsyncServerTest extends PlayServerTest { - @Override - TestServer startServer(int port) { - def server = AsyncServer.server(port) - server.start() - return server - } -} diff --git a/instrumentation/play/play-2.3/src/test/groovy/server/PlayServerTest.groovy b/instrumentation/play/play-2.3/src/test/groovy/server/PlayServerTest.groovy deleted file mode 100644 index c6aee75842..0000000000 --- a/instrumentation/play/play-2.3/src/test/groovy/server/PlayServerTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.sdk.trace.data.SpanData -import play.api.test.TestServer - -class PlayServerTest extends HttpServerTest { - @Override - TestServer startServer(int port) { - def server = SyncServer.server(port) - server.start() - return server - } - - @Override - void stopServer(TestServer server) { - server.stop() - } - - @Override - boolean hasHandlerSpan() { - true - } - - @Override - void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) { - trace.span(index) { - name "play.request" - kind INTERNAL - errored endpoint == EXCEPTION - if (endpoint == EXCEPTION) { - errorEvent(Exception, EXCEPTION.body) - } - childOf((SpanData) parent) - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "netty.request" - } -} diff --git a/instrumentation/play/play-2.3/src/test/scala/server/AsyncServer.scala b/instrumentation/play/play-2.3/src/test/scala/server/AsyncServer.scala deleted file mode 100644 index 8225cdbffe..0000000000 --- a/instrumentation/play/play-2.3/src/test/scala/server/AsyncServer.scala +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ -import play.api.mvc.{Action, Handler, Results} -import play.api.test.{FakeApplication, TestServer} - -import scala.concurrent.Future - -object AsyncServer { - val routes: PartialFunction[(String, String), Handler] = { - case ("GET", "/success") => - Action.async { request => - HttpServerTest.controller( - SUCCESS, - new AsyncControllerClosureAdapter( - Future.successful( - Results.Status(SUCCESS.getStatus).apply(SUCCESS.getBody) - ) - ) - ) - } - case ("GET", "/redirect") => - Action.async { request => - HttpServerTest.controller( - REDIRECT, - new AsyncControllerClosureAdapter( - Future.successful( - Results.Redirect(REDIRECT.getBody, REDIRECT.getStatus) - ) - ) - ) - } - case ("GET", "/query") => - Action.async { result => - HttpServerTest.controller( - QUERY_PARAM, - new AsyncControllerClosureAdapter( - Future.successful( - Results.Status(QUERY_PARAM.getStatus).apply(QUERY_PARAM.getBody) - ) - ) - ) - } - case ("GET", "/error-status") => - Action.async { result => - HttpServerTest.controller( - ERROR, - new AsyncControllerClosureAdapter( - Future - .successful(Results.Status(ERROR.getStatus).apply(ERROR.getBody)) - ) - ) - } - case ("GET", "/exception") => - Action.async { result => - HttpServerTest.controller( - EXCEPTION, - new AsyncBlockClosureAdapter(() => { - throw new Exception(EXCEPTION.getBody) - }) - ) - } - } - - def server(port: Int): TestServer = { - TestServer( - port, - FakeApplication(withGlobal = Some(new Settings()), withRoutes = routes) - ) - } -} diff --git a/instrumentation/play/play-2.3/src/test/scala/server/ControllerClosureAdapter.scala b/instrumentation/play/play-2.3/src/test/scala/server/ControllerClosureAdapter.scala deleted file mode 100644 index 3e4f5b4155..0000000000 --- a/instrumentation/play/play-2.3/src/test/scala/server/ControllerClosureAdapter.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import groovy.lang.Closure -import play.api.mvc.Result - -import scala.concurrent.Future - -class ControllerClosureAdapter(response: Result) extends Closure[Result] { - override def call(): Result = response -} - -class BlockClosureAdapter(block: () => Result) extends Closure[Result] { - override def call(): Result = block() -} - -class AsyncControllerClosureAdapter(response: Future[Result]) - extends Closure[Future[Result]] { - override def call(): Future[Result] = response -} - -class AsyncBlockClosureAdapter(block: () => Future[Result]) - extends Closure[Future[Result]] { - override def call(): Future[Result] = block() -} diff --git a/instrumentation/play/play-2.3/src/test/scala/server/Settings.scala b/instrumentation/play/play-2.3/src/test/scala/server/Settings.scala deleted file mode 100644 index 16b2a477c8..0000000000 --- a/instrumentation/play/play-2.3/src/test/scala/server/Settings.scala +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import play.api.GlobalSettings -import play.api.mvc.{RequestHeader, Result, Results} - -import scala.concurrent.Future - -class Settings extends GlobalSettings { - override def onError( - request: RequestHeader, - ex: Throwable - ): Future[Result] = { - Future.successful(Results.InternalServerError(ex.getCause.getMessage)) - } -} diff --git a/instrumentation/play/play-2.3/src/test/scala/server/SyncServer.scala b/instrumentation/play/play-2.3/src/test/scala/server/SyncServer.scala deleted file mode 100644 index 8a7b62fb5a..0000000000 --- a/instrumentation/play/play-2.3/src/test/scala/server/SyncServer.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint._ -import play.api.mvc.{Action, Handler, Results} -import play.api.test.{FakeApplication, TestServer} - -object SyncServer { - val routes: PartialFunction[(String, String), Handler] = { - case ("GET", "/success") => - Action { request => - HttpServerTest.controller( - SUCCESS, - new ControllerClosureAdapter( - Results.Status(SUCCESS.getStatus).apply(SUCCESS.getBody) - ) - ) - } - case ("GET", "/redirect") => - Action { request => - HttpServerTest.controller( - REDIRECT, - new ControllerClosureAdapter( - Results.Redirect(REDIRECT.getBody, REDIRECT.getStatus) - ) - ) - } - case ("GET", "/query") => - Action { request => - HttpServerTest.controller( - QUERY_PARAM, - new ControllerClosureAdapter( - Results.Status(QUERY_PARAM.getStatus).apply(QUERY_PARAM.getBody) - ) - ) - } - case ("GET", "/error-status") => - Action { request => - HttpServerTest.controller( - ERROR, - new ControllerClosureAdapter( - Results.Status(ERROR.getStatus).apply(ERROR.getBody) - ) - ) - } - case ("GET", "/exception") => - Action { request => - HttpServerTest.controller(EXCEPTION, new BlockClosureAdapter(() => { - throw new Exception(EXCEPTION.getBody) - })) - } - } - - def server(port: Int): TestServer = { - TestServer( - port, - FakeApplication(withGlobal = Some(new Settings()), withRoutes = routes) - ) - } -} diff --git a/instrumentation/play/play-2.4/javaagent/src/test/groovy/server/PlayServerTest.groovy b/instrumentation/play/play-2.4/javaagent/src/test/groovy/server/PlayServerTest.groovy index dda8a00dec..2803308449 100644 --- a/instrumentation/play/play-2.4/javaagent/src/test/groovy/server/PlayServerTest.groovy +++ b/instrumentation/play/play-2.4/javaagent/src/test/groovy/server/PlayServerTest.groovy @@ -5,12 +5,12 @@ package server +import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.base.HttpServerTest diff --git a/instrumentation/play/play-2.4/play-2.4.gradle b/instrumentation/play/play-2.4/play-2.4.gradle deleted file mode 100644 index 9ce46323e2..0000000000 --- a/instrumentation/play/play-2.4/play-2.4.gradle +++ /dev/null @@ -1,48 +0,0 @@ -ext { - // Play doesn't work with Java 9+ until 2.6.12 - maxJavaVersionForTests = JavaVersion.VERSION_1_8 -} - -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = 'com.typesafe.play' - module = 'play_2.11' - versions = '[2.4.0,2.6)' - assertInverse = true - } - fail { - group = 'com.typesafe.play' - module = 'play_2.12' - versions = '[,]' - } - fail { - group = 'com.typesafe.play' - module = 'play_2.13' - versions = '[,]' - } -} - -dependencies { - // TODO(anuraaga): Something about library configuration doesn't work well with scala compilation - // here. - compileOnly group: 'com.typesafe.play', name: 'play_2.11', version: '2.4.0' - - testImplementation project(':instrumentation:netty:netty-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:akka-http-10.0') - - // Before 2.5, play used netty 3.x which isn't supported, so for better test consistency, we test with just 2.5 - testLibrary group: 'com.typesafe.play', name: 'play-java_2.11', version: '2.5.0' - testLibrary group: 'com.typesafe.play', name: 'play-java-ws_2.11', version: '2.5.0' - testLibrary(group: 'com.typesafe.play', name: 'play-test_2.11', version: '2.5.0') { - exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client' - } - - latestDepTestLibrary group: 'com.typesafe.play', name: 'play-java_2.11', version: '2.5.+' - latestDepTestLibrary group: 'com.typesafe.play', name: 'play-java-ws_2.11', version: '2.5.+' - latestDepTestLibrary(group: 'com.typesafe.play', name: 'play-test_2.11', version: '2.5.+') { - exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client' - } -} diff --git a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayAdvice.java b/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayAdvice.java deleted file mode 100644 index 4cdc682b50..0000000000 --- a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayAdvice.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_4; - -import static io.opentelemetry.javaagent.instrumentation.play.v2_4.PlayTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import net.bytebuddy.asm.Advice; -import play.api.mvc.Action; -import play.api.mvc.Headers; -import play.api.mvc.Request; -import play.api.mvc.Result; -import scala.concurrent.Future; - -public class PlayAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope onEnter(@Advice.Argument(0) Request req) { - Span span = tracer().startSpan("play.request", Kind.INTERNAL); - return new SpanWithScope(span, span.makeCurrent()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopTraceOnResponse( - @Advice.Enter SpanWithScope playControllerScope, - @Advice.This Object thisAction, - @Advice.Thrown Throwable throwable, - @Advice.Argument(0) Request req, - @Advice.Return(readOnly = false) Future responseFuture) { - Span playControllerSpan = playControllerScope.getSpan(); - - // Call onRequest on return after tags are populated. - tracer().updateSpanName(playControllerSpan, req); - - if (throwable == null) { - responseFuture.onComplete( - new RequestCompleteCallback(playControllerSpan), - ((Action) thisAction).executionContext()); - } else { - tracer().endExceptionally(playControllerSpan, throwable); - } - playControllerScope.closeScope(); - // span finished in RequestCompleteCallback - - Span rootSpan = BaseTracer.getCurrentServerSpan(); - // set the span name on the upstream akka/netty span - tracer().updateSpanName(rootSpan, req); - } - - // Unused method for muzzle - public static void muzzleCheck(Headers headers) { - // This distinguishes between 2.3 and 2.4, excluding the former - headers.get("aKey"); - // system() method was removed in 2.6, so this line prevents from applying in play 2.6 - play.libs.Akka.system(); - } -} diff --git a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayInstrumentationModule.java b/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayInstrumentationModule.java deleted file mode 100644 index 8f2e6513dd..0000000000 --- a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayInstrumentationModule.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_4; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class PlayInstrumentationModule extends InstrumentationModule { - - public PlayInstrumentationModule() { - super("play", "play-2.4"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ActionInstrumentation()); - } - - public static class ActionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("play.api.mvc.Action"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("play.api.mvc.Action")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("apply") - .and(takesArgument(0, named("play.api.mvc.Request"))) - .and(returns(named("scala.concurrent.Future"))), - PlayAdvice.class.getName()); - } - } -} diff --git a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayTracer.java b/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayTracer.java deleted file mode 100644 index 65383e040c..0000000000 --- a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayTracer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_4; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.UndeclaredThrowableException; -import play.api.mvc.Request; -import scala.Option; - -public class PlayTracer extends BaseTracer { - private static final PlayTracer TRACER = new PlayTracer(); - - public static PlayTracer tracer() { - return TRACER; - } - - public void updateSpanName(Span span, Request request) { - if (request != null) { - Option pathOption = request.tags().get("ROUTE_PATTERN"); - if (!pathOption.isEmpty()) { - String path = pathOption.get(); - span.updateName(path); - } - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.play"; - } - - @Override - protected Throwable unwrapThrowable(Throwable throwable) { - // This can be moved to instanceof check when using Java 8. - if (throwable.getClass().getName().equals("java.util.concurrent.CompletionException") - && throwable.getCause() != null) { - throwable = throwable.getCause(); - } - while ((throwable instanceof InvocationTargetException - || throwable instanceof UndeclaredThrowableException) - && throwable.getCause() != null) { - throwable = throwable.getCause(); - } - return throwable; - } -} diff --git a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java b/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java deleted file mode 100644 index abcd254b9f..0000000000 --- a/instrumentation/play/play-2.4/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_4; - -import static io.opentelemetry.javaagent.instrumentation.play.v2_4.PlayTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import play.api.mvc.Result; -import scala.util.Try; - -public class RequestCompleteCallback extends scala.runtime.AbstractFunction1, Object> { - - private static final Logger log = LoggerFactory.getLogger(RequestCompleteCallback.class); - - private final Span span; - - public RequestCompleteCallback(Span span) { - this.span = span; - } - - @Override - public Object apply(Try result) { - try { - if (result.isFailure()) { - tracer().endExceptionally(span, result.failed().get()); - } else { - tracer().end(span); - } - } catch (Throwable t) { - log.debug("error in play instrumentation", t); - } - return null; - } -} diff --git a/instrumentation/play/play-2.4/src/test/groovy/client/PlayWsClientTest.groovy b/instrumentation/play/play-2.4/src/test/groovy/client/PlayWsClientTest.groovy deleted file mode 100644 index 829e23715f..0000000000 --- a/instrumentation/play/play-2.4/src/test/groovy/client/PlayWsClientTest.groovy +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package client - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import play.libs.ws.WS -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Subject -import spock.lang.Timeout - -// Play 2.6+ uses a separately versioned client that shades the underlying dependency -// This means our built in instrumentation won't work. -@Timeout(5) -class PlayWsClientTest extends HttpClientTest { - @Subject - @Shared - @AutoCleanup - def client = WS.newClient(-1) - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - def request = client.url(uri.toString()) - headers.entrySet().each { - request.setHeader(it.key, it.value) - } - - def status = request.execute(method).thenApply { - callback?.call() - it - }.thenApply { - it.status - } - return status.toCompletableFuture().get() - } - - @Override - String userAgent() { - return "AHC" - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } -} diff --git a/instrumentation/play/play-2.4/src/test/groovy/server/PlayAsyncServerTest.groovy b/instrumentation/play/play-2.4/src/test/groovy/server/PlayAsyncServerTest.groovy deleted file mode 100644 index 9de58e6fee..0000000000 --- a/instrumentation/play/play-2.4/src/test/groovy/server/PlayAsyncServerTest.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import java.util.concurrent.CompletableFuture -import java.util.function.Supplier -import play.libs.concurrent.HttpExecution -import play.mvc.Results -import play.routing.RoutingDsl -import play.server.Server - -class PlayAsyncServerTest extends PlayServerTest { - @Override - Server startServer(int port) { - def router = - new RoutingDsl() - .GET(SUCCESS.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(SUCCESS) { - Results.status(SUCCESS.getStatus(), SUCCESS.getBody()) - } - }, HttpExecution.defaultContext()) - } as Supplier) - .GET(QUERY_PARAM.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(QUERY_PARAM) { - Results.status(QUERY_PARAM.getStatus(), QUERY_PARAM.getBody()) - } - }, HttpExecution.defaultContext()) - } as Supplier) - .GET(REDIRECT.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(REDIRECT) { - Results.found(REDIRECT.getBody()) - } - }, HttpExecution.defaultContext()) - } as Supplier) - .GET(ERROR.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(ERROR) { - Results.status(ERROR.getStatus(), ERROR.getBody()) - } - }, HttpExecution.defaultContext()) - } as Supplier) - .GET(EXCEPTION.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(EXCEPTION) { - throw new Exception(EXCEPTION.getBody()) - } - }, HttpExecution.defaultContext()) - } as Supplier) - - return Server.forRouter(router.build(), port) - } -} diff --git a/instrumentation/play/play-2.4/src/test/groovy/server/PlayServerTest.groovy b/instrumentation/play/play-2.4/src/test/groovy/server/PlayServerTest.groovy deleted file mode 100644 index 2803308449..0000000000 --- a/instrumentation/play/play-2.4/src/test/groovy/server/PlayServerTest.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.function.Supplier -import play.mvc.Results -import play.routing.RoutingDsl -import play.server.Server - -class PlayServerTest extends HttpServerTest { - @Override - Server startServer(int port) { - def router = - new RoutingDsl() - .GET(SUCCESS.getPath()).routeTo({ - controller(SUCCESS) { - Results.status(SUCCESS.getStatus(), SUCCESS.getBody()) - } - } as Supplier) - .GET(QUERY_PARAM.getPath()).routeTo({ - controller(QUERY_PARAM) { - Results.status(QUERY_PARAM.getStatus(), QUERY_PARAM.getBody()) - } - } as Supplier) - .GET(REDIRECT.getPath()).routeTo({ - controller(REDIRECT) { - Results.found(REDIRECT.getBody()) - } - } as Supplier) - .GET(ERROR.getPath()).routeTo({ - controller(ERROR) { - Results.status(ERROR.getStatus(), ERROR.getBody()) - } - } as Supplier) - .GET(EXCEPTION.getPath()).routeTo({ - controller(EXCEPTION) { - throw new Exception(EXCEPTION.getBody()) - } - } as Supplier) - - return Server.forRouter(router.build(), port) - } - - @Override - void stopServer(Server server) { - server.stop() - } - - @Override - boolean hasHandlerSpan() { - true - } - - boolean testExceptionBody() { - // I can't figure out how to set a proper exception handler to customize the response body. - false - } - - @Override - void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) { - trace.span(index) { - name "play.request" - kind INTERNAL - errored endpoint == EXCEPTION - if (endpoint == EXCEPTION) { - errorEvent(Exception, EXCEPTION.body) - } - childOf((SpanData) parent) - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "netty.request" - } - -} diff --git a/instrumentation/play/play-2.6/javaagent/src/test/groovy/server/PlayServerTest.groovy b/instrumentation/play/play-2.6/javaagent/src/test/groovy/server/PlayServerTest.groovy index 83ffea0360..0e041c3c5b 100644 --- a/instrumentation/play/play-2.6/javaagent/src/test/groovy/server/PlayServerTest.groovy +++ b/instrumentation/play/play-2.6/javaagent/src/test/groovy/server/PlayServerTest.groovy @@ -5,12 +5,12 @@ package server +import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.base.HttpServerTest diff --git a/instrumentation/play/play-2.6/play-2.6.gradle b/instrumentation/play/play-2.6/play-2.6.gradle deleted file mode 100644 index 501a9c9a99..0000000000 --- a/instrumentation/play/play-2.6/play-2.6.gradle +++ /dev/null @@ -1,52 +0,0 @@ -ext { - // Play doesn't work with Java 9+ until 2.6.12 - maxJavaVersionForTests = JavaVersion.VERSION_1_8 -} - -apply from: "$rootDir/gradle/instrumentation.gradle" - -def scalaVersion = '2.11' -def playVersion = '2.6.0' - -muzzle { - pass { - group = 'com.typesafe.play' - module = "play_$scalaVersion" - versions = "[$playVersion,)" - assertInverse = true - } - pass { - group = 'com.typesafe.play' - module = 'play_2.12' - versions = "[$playVersion,)" - assertInverse = true - } - pass { - group = 'com.typesafe.play' - module = 'play_2.13' - versions = "[$playVersion,)" - assertInverse = true - } -} - -dependencies { - // TODO(anuraaga): Something about library configuration doesn't work well with scala compilation - // here. - compileOnly group: 'com.typesafe.play', name: "play_$scalaVersion", version: playVersion - - testImplementation project(':instrumentation:netty:netty-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:akka-http-10.0') - - testLibrary group: 'com.typesafe.play', name: "play-java_$scalaVersion", version: playVersion - // TODO: Play WS is a separately versioned library starting with 2.6 and needs separate instrumentation. - testLibrary(group: 'com.typesafe.play', name: "play-test_$scalaVersion", version: playVersion) { - exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client' - } - - // TODO: This should be changed to the latest in scala 2.13 instead of 2.11 since its ahead - latestDepTestLibrary group: 'com.typesafe.play', name: "play-java_$scalaVersion", version: '2.+' - latestDepTestLibrary(group: 'com.typesafe.play', name: "play-test_$scalaVersion", version: '2.+') { - exclude group: 'org.eclipse.jetty.websocket', module: 'websocket-client' - } -} diff --git a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayAdvice.java b/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayAdvice.java deleted file mode 100644 index cf64aecfc8..0000000000 --- a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayAdvice.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_6; - -import static io.opentelemetry.javaagent.instrumentation.play.v2_6.PlayTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.javaagent.instrumentation.api.SpanWithScope; -import net.bytebuddy.asm.Advice; -import play.api.mvc.Action; -import play.api.mvc.Request; -import play.api.mvc.Result; -import scala.concurrent.Future; - -public class PlayAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static SpanWithScope onEnter(@Advice.Argument(0) Request req) { - Span span = tracer().startSpan("play.request", Kind.INTERNAL); - - return new SpanWithScope(span, span.makeCurrent()); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopTraceOnResponse( - @Advice.Enter SpanWithScope playControllerScope, - @Advice.This Object thisAction, - @Advice.Thrown Throwable throwable, - @Advice.Argument(0) Request req, - @Advice.Return(readOnly = false) Future responseFuture) { - Span playControllerSpan = playControllerScope.getSpan(); - - // Call onRequest on return after tags are populated. - tracer().updateSpanName(playControllerSpan, req); - - if (throwable == null) { - responseFuture.onComplete( - new RequestCompleteCallback(playControllerSpan), - ((Action) thisAction).executionContext()); - } else { - tracer().endExceptionally(playControllerSpan, throwable); - } - playControllerScope.closeScope(); - // span finished in RequestCompleteCallback - - Span rootSpan = BaseTracer.getCurrentServerSpan(); - // set the span name on the upstream akka/netty span - tracer().updateSpanName(rootSpan, req); - } -} diff --git a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayInstrumentationModule.java b/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayInstrumentationModule.java deleted file mode 100644 index 18965ea975..0000000000 --- a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayInstrumentationModule.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_6; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class PlayInstrumentationModule extends InstrumentationModule { - - public PlayInstrumentationModule() { - super("play", "play-2.6"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ActionInstrumentation()); - } - - public static class ActionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("play.api.mvc.Action"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("play.api.mvc.Action")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("apply") - .and(takesArgument(0, named("play.api.mvc.Request"))) - .and(returns(named("scala.concurrent.Future"))), - PlayAdvice.class.getName()); - } - } -} diff --git a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayTracer.java b/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayTracer.java deleted file mode 100644 index e40f6bbc5f..0000000000 --- a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayTracer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_6; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.UndeclaredThrowableException; -import play.api.mvc.Request; -import play.api.routing.HandlerDef; -import play.libs.typedmap.TypedKey; -import play.routing.Router; -import scala.Option; - -public class PlayTracer extends BaseTracer { - private static final PlayTracer TRACER = new PlayTracer(); - - public static PlayTracer tracer() { - return TRACER; - } - - private static final Method typedKeyGetUnderlying; - - static { - Method typedKeyGetUnderlyingCheck = null; - try { - // This method was added in Play 2.6.8 - typedKeyGetUnderlyingCheck = TypedKey.class.getMethod("asScala"); - } catch (NoSuchMethodException ignored) { - } - // Fallback - if (typedKeyGetUnderlyingCheck == null) { - try { - typedKeyGetUnderlyingCheck = TypedKey.class.getMethod("underlying"); - } catch (NoSuchMethodException ignored) { - } - } - typedKeyGetUnderlying = typedKeyGetUnderlyingCheck; - } - - public void updateSpanName(Span span, Request request) { - if (request != null) { - // more about routes here: - // https://github.com/playframework/playframework/blob/master/documentation/manual/releases/release26/migration26/Migration26.md - Option defOption = null; - if (typedKeyGetUnderlying != null) { // Should always be non-null but just to make sure - try { - defOption = - request - .attrs() - .get( - (play.api.libs.typedmap.TypedKey) - typedKeyGetUnderlying.invoke(Router.Attrs.HANDLER_DEF)); - } catch (IllegalAccessException | InvocationTargetException ignored) { - } - } - if (defOption != null && !defOption.isEmpty()) { - String path = defOption.get().path(); - span.updateName(path); - } - } - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.play"; - } - - @Override - protected Throwable unwrapThrowable(Throwable throwable) { - // This can be moved to instanceof check when using Java 8. - if (throwable.getClass().getName().equals("java.util.concurrent.CompletionException") - && throwable.getCause() != null) { - throwable = throwable.getCause(); - } - while ((throwable instanceof InvocationTargetException - || throwable instanceof UndeclaredThrowableException) - && throwable.getCause() != null) { - throwable = throwable.getCause(); - } - return throwable; - } -} diff --git a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/RequestCompleteCallback.java b/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/RequestCompleteCallback.java deleted file mode 100644 index cba0231a46..0000000000 --- a/instrumentation/play/play-2.6/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/RequestCompleteCallback.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.play.v2_6; - -import static io.opentelemetry.javaagent.instrumentation.play.v2_6.PlayTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import play.api.mvc.Result; -import scala.util.Try; - -public class RequestCompleteCallback extends scala.runtime.AbstractFunction1, Object> { - - private static final Logger log = LoggerFactory.getLogger(RequestCompleteCallback.class); - - private final Span span; - - public RequestCompleteCallback(Span span) { - this.span = span; - } - - @Override - public Object apply(Try result) { - try { - if (result.isFailure()) { - tracer().endExceptionally(span, result.failed().get()); - } else { - tracer().end(span); - } - } catch (Throwable t) { - log.debug("error in play instrumentation", t); - } - return null; - } -} diff --git a/instrumentation/play/play-2.6/src/test/groovy/server/PlayAsyncServerTest.groovy b/instrumentation/play/play-2.6/src/test/groovy/server/PlayAsyncServerTest.groovy deleted file mode 100644 index b40b9cd079..0000000000 --- a/instrumentation/play/play-2.6/src/test/groovy/server/PlayAsyncServerTest.groovy +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import java.util.concurrent.CompletableFuture -import java.util.concurrent.Executors -import java.util.function.Supplier -import play.BuiltInComponents -import play.Mode -import play.libs.concurrent.HttpExecution -import play.mvc.Results -import play.routing.RoutingDsl -import play.server.Server -import spock.lang.Shared - -class PlayAsyncServerTest extends PlayServerTest { - @Shared - def executor = Executors.newCachedThreadPool() - - def cleanupSpec() { - executor.shutdown() - } - - @Override - Server startServer(int port) { - def execContext = HttpExecution.fromThread(executor) - return Server.forRouter(Mode.TEST, port) { BuiltInComponents components -> - RoutingDsl.fromComponents(components) - .GET(SUCCESS.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(SUCCESS) { - Results.status(SUCCESS.getStatus(), SUCCESS.getBody()) - } - }, execContext) - } as Supplier) - .GET(QUERY_PARAM.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(QUERY_PARAM) { - Results.status(QUERY_PARAM.getStatus(), QUERY_PARAM.getBody()) - } - }, execContext) - } as Supplier) - .GET(REDIRECT.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(REDIRECT) { - Results.found(REDIRECT.getBody()) - } - }, execContext) - } as Supplier) - .GET(ERROR.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(ERROR) { - Results.status(ERROR.getStatus(), ERROR.getBody()) - } - }, execContext) - } as Supplier) - .GET(EXCEPTION.getPath()).routeAsync({ - CompletableFuture.supplyAsync({ - controller(EXCEPTION) { - throw new Exception(EXCEPTION.getBody()) - } - }, execContext) - } as Supplier) - .build() - } - } -} diff --git a/instrumentation/play/play-2.6/src/test/groovy/server/PlayServerTest.groovy b/instrumentation/play/play-2.6/src/test/groovy/server/PlayServerTest.groovy deleted file mode 100644 index 0e041c3c5b..0000000000 --- a/instrumentation/play/play-2.6/src/test/groovy/server/PlayServerTest.groovy +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.function.Supplier -import play.BuiltInComponents -import play.Mode -import play.mvc.Results -import play.routing.RoutingDsl -import play.server.Server - -class PlayServerTest extends HttpServerTest { - @Override - Server startServer(int port) { - return Server.forRouter(Mode.TEST, port) { BuiltInComponents components -> - RoutingDsl.fromComponents(components) - .GET(SUCCESS.getPath()).routeTo({ - controller(SUCCESS) { - Results.status(SUCCESS.getStatus(), SUCCESS.getBody()) - } - } as Supplier) - .GET(QUERY_PARAM.getPath()).routeTo({ - controller(QUERY_PARAM) { - Results.status(QUERY_PARAM.getStatus(), QUERY_PARAM.getBody()) - } - } as Supplier) - .GET(REDIRECT.getPath()).routeTo({ - controller(REDIRECT) { - Results.found(REDIRECT.getBody()) - } - } as Supplier) - .GET(ERROR.getPath()).routeTo({ - controller(ERROR) { - Results.status(ERROR.getStatus(), ERROR.getBody()) - } - } as Supplier) - .GET(EXCEPTION.getPath()).routeTo({ - controller(EXCEPTION) { - throw new Exception(EXCEPTION.getBody()) - } - } as Supplier) - .build() - } - } - - @Override - void stopServer(Server server) { - server.stop() - } - - @Override - boolean hasHandlerSpan() { - true - } - - boolean testExceptionBody() { - // I can't figure out how to set a proper exception handler to customize the response body. - false - } - - @Override - void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) { - trace.span(index) { - name "play.request" - kind INTERNAL - errored endpoint == EXCEPTION - childOf((SpanData) parent) - if (endpoint == EXCEPTION) { - errorEvent(Exception, EXCEPTION.body) - } - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return "akka.request" - } - -} diff --git a/instrumentation/rabbitmq-2.7/rabbitmq-2.7.gradle b/instrumentation/rabbitmq-2.7/rabbitmq-2.7.gradle deleted file mode 100644 index b1a6708e30..0000000000 --- a/instrumentation/rabbitmq-2.7/rabbitmq-2.7.gradle +++ /dev/null @@ -1,24 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.rabbitmq" - module = 'amqp-client' - versions = "[2.7.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'com.rabbitmq', name: 'amqp-client', version: '2.7.0' - - testLibrary group: 'org.springframework.amqp', name: 'spring-rabbit', version: '1.1.0.RELEASE' - - testImplementation deps.testcontainers -} - -configurations.testRuntime { - resolutionStrategy { - force group: 'com.rabbitmq', name: 'amqp-client', version: '2.7.0' - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitChannelInstrumentation.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitChannelInstrumentation.java deleted file mode 100644 index a7ed8e2b3d..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitChannelInstrumentation.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import static io.opentelemetry.javaagent.instrumentation.rabbitmq.RabbitCommandInstrumentation.SpanHolder.CURRENT_RABBIT_SPAN; -import static io.opentelemetry.javaagent.instrumentation.rabbitmq.RabbitTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static net.bytebuddy.matcher.ElementMatchers.canThrow; -import static net.bytebuddy.matcher.ElementMatchers.isGetter; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.isSetter; -import static net.bytebuddy.matcher.ElementMatchers.nameEndsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Channel; -import com.rabbitmq.client.Consumer; -import com.rabbitmq.client.GetResponse; -import com.rabbitmq.client.MessageProperties; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class RabbitChannelInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.rabbitmq.client.Channel"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("com.rabbitmq.client.Channel")); - } - - @Override - public Map, String> transformers() { - // We want the advice applied in a specific order, so use an ordered map. - Map, String> transformers = new LinkedHashMap<>(); - transformers.put( - isMethod() - .and( - not( - isGetter() - .or(isSetter()) - .or(nameEndsWith("Listener")) - .or(nameEndsWith("Listeners")) - .or(namedOneOf("processAsync", "open", "close", "abort", "basicGet")))) - .and(isPublic()) - .and(canThrow(IOException.class).or(canThrow(InterruptedException.class))), - RabbitChannelInstrumentation.class.getName() + "$ChannelMethodAdvice"); - transformers.put( - isMethod().and(named("basicPublish")).and(takesArguments(6)), - RabbitChannelInstrumentation.class.getName() + "$ChannelPublishAdvice"); - transformers.put( - isMethod().and(named("basicGet")).and(takesArgument(0, String.class)), - RabbitChannelInstrumentation.class.getName() + "$ChannelGetAdvice"); - transformers.put( - isMethod() - .and(named("basicConsume")) - .and(takesArgument(0, String.class)) - .and(takesArgument(6, named("com.rabbitmq.client.Consumer"))), - RabbitChannelInstrumentation.class.getName() + "$ChannelConsumeAdvice"); - return transformers; - } - - // TODO Why do we start span here and not in ChannelPublishAdvice below? - public static class ChannelMethodAdvice { - @Advice.OnMethodEnter - public static void onEnter( - @Advice.This Channel channel, - @Advice.Origin("Channel.#m") String method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(Channel.class); - if (callDepth > 0) { - return; - } - - span = tracer().startSpan(method, channel.getConnection()); - CURRENT_RABBIT_SPAN.set(span); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - CallDepthThreadLocalMap.reset(Channel.class); - - CURRENT_RABBIT_SPAN.remove(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } - - public static class ChannelPublishAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void setSpanNameAddHeaders( - @Advice.Argument(0) String exchange, - @Advice.Argument(1) String routingKey, - @Advice.Argument(value = 4, readOnly = false) AMQP.BasicProperties props, - @Advice.Argument(5) byte[] body) { - Span span = Java8BytecodeBridge.currentSpan(); - - if (span.getSpanContext().isValid()) { - tracer().onPublish(span, exchange, routingKey); - if (body != null) { - span.setAttribute( - SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, (long) body.length); - } - - // This is the internal behavior when props are null. We're just doing it earlier now. - if (props == null) { - props = MessageProperties.MINIMAL_BASIC; - } - Integer deliveryMode = props.getDeliveryMode(); - if (deliveryMode != null) { - span.setAttribute("amqp.delivery_mode", deliveryMode); - } - - // We need to copy the BasicProperties and provide a header map we can modify - Map headers = props.getHeaders(); - headers = (headers == null) ? new HashMap<>() : new HashMap<>(headers); - - Context context = Java8BytecodeBridge.currentContext().with(span); - - Java8BytecodeBridge.getGlobalPropagators() - .getTextMapPropagator() - .inject(context, headers, TextMapInjectAdapter.SETTER); - - props = - new AMQP.BasicProperties( - props.getContentType(), - props.getContentEncoding(), - headers, - props.getDeliveryMode(), - props.getPriority(), - props.getCorrelationId(), - props.getReplyTo(), - props.getExpiration(), - props.getMessageId(), - props.getTimestamp(), - props.getType(), - props.getUserId(), - props.getAppId(), - props.getClusterId()); - } - } - } - - public static class ChannelGetAdvice { - @Advice.OnMethodEnter - public static long takeTimestamp(@Advice.Local("callDepth") int callDepth) { - - callDepth = CallDepthThreadLocalMap.incrementCallDepth(Channel.class); - return System.currentTimeMillis(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void extractAndStartSpan( - @Advice.This Channel channel, - @Advice.Argument(0) String queue, - @Advice.Enter long startTime, - @Advice.Local("callDepth") int callDepth, - @Advice.Return GetResponse response, - @Advice.Thrown Throwable throwable) { - if (callDepth > 0) { - return; - } - CallDepthThreadLocalMap.reset(Channel.class); - - // can't create span and put into scope in method enter above, because can't add parent after - // span creation - Span span = tracer().startGetSpan(queue, startTime, response, channel.getConnection()); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } - - public static class ChannelConsumeAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void wrapConsumer( - @Advice.Argument(0) String queue, - @Advice.Argument(value = 6, readOnly = false) Consumer consumer) { - // We have to save off the queue name here because it isn't available to the consumer later. - if (consumer != null && !(consumer instanceof TracedDelegatingConsumer)) { - consumer = new TracedDelegatingConsumer(queue, consumer); - } - } - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitCommandInstrumentation.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitCommandInstrumentation.java deleted file mode 100644 index f66cf05299..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitCommandInstrumentation.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import static io.opentelemetry.javaagent.instrumentation.rabbitmq.RabbitCommandInstrumentation.SpanHolder.CURRENT_RABBIT_SPAN; -import static io.opentelemetry.javaagent.instrumentation.rabbitmq.RabbitTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isConstructor; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.rabbitmq.client.Command; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class RabbitCommandInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("com.rabbitmq.client.Command"); - } - - @Override - public ElementMatcher typeMatcher() { - return implementsInterface(named("com.rabbitmq.client.Command")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isConstructor(), - RabbitCommandInstrumentation.class.getName() + "$CommandConstructorAdvice"); - } - - public static class SpanHolder { - public static final ThreadLocal CURRENT_RABBIT_SPAN = new ThreadLocal<>(); - } - - public static class CommandConstructorAdvice { - @Advice.OnMethodExit - public static void setSpanNameAddHeaders(@Advice.This Command command) { - - Span span = CURRENT_RABBIT_SPAN.get(); - if (span != null && command.getMethod() != null) { - tracer().onCommand(span, command); - } - } - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitMqInstrumentationModule.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitMqInstrumentationModule.java deleted file mode 100644 index 6bc6a732df..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitMqInstrumentationModule.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class RabbitMqInstrumentationModule extends InstrumentationModule { - public RabbitMqInstrumentationModule() { - super("rabbitmq", "rabbitmq-2.7"); - } - - @Override - public List typeInstrumentations() { - return asList(new RabbitChannelInstrumentation(), new RabbitCommandInstrumentation()); - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitTracer.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitTracer.java deleted file mode 100644 index 8e760fee62..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitTracer.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT; -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER; -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER; -import static io.opentelemetry.javaagent.instrumentation.rabbitmq.TextMapExtractAdapter.GETTER; -import static java.util.concurrent.TimeUnit.NANOSECONDS; - -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Command; -import com.rabbitmq.client.Connection; -import com.rabbitmq.client.Envelope; -import com.rabbitmq.client.GetResponse; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import io.opentelemetry.instrumentation.api.tracer.utils.NetPeerUtils; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -public class RabbitTracer extends BaseTracer { - - private static final RabbitTracer TRACER = new RabbitTracer(); - - public static RabbitTracer tracer() { - return TRACER; - } - - public Span startSpan(String method, Connection connection) { - Span.Kind kind = method.equals("Channel.basicPublish") ? PRODUCER : CLIENT; - Span span = startSpan(method, kind); - span.setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "rabbitmq"); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "queue"); - - NetPeerUtils.setNetPeer(span, connection.getAddress(), connection.getPort()); - - return span; - } - - public Span startGetSpan( - String queue, long startTime, GetResponse response, Connection connection) { - SpanBuilder spanBuilder = - tracer - .spanBuilder(spanNameOnGet(queue)) - .setSpanKind(CLIENT) - .setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "rabbitmq") - .setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "queue") - .setAttribute(SemanticAttributes.MESSAGING_OPERATION, "receive") - .setStartTimestamp(startTime, TimeUnit.MILLISECONDS); - - Span span = spanBuilder.startSpan(); - if (response != null) { - span.setAttribute( - SemanticAttributes.MESSAGING_DESTINATION, - normalizeExchangeName(response.getEnvelope().getExchange())); - span.setAttribute("messaging.rabbitmq.routing_key", response.getEnvelope().getRoutingKey()); - span.setAttribute( - SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, - (long) response.getBody().length); - } - NetPeerUtils.setNetPeer(span, connection.getAddress(), connection.getPort()); - onGet(span, queue); - - return span; - } - - public Span startDeliverySpan( - String queue, Envelope envelope, AMQP.BasicProperties properties, byte[] body) { - Map headers = properties.getHeaders(); - long startTimeMillis = System.currentTimeMillis(); - Span span = - tracer - .spanBuilder(spanNameOnDeliver(queue)) - .setSpanKind(CONSUMER) - .setParent(extract(headers, GETTER)) - .setStartTimestamp(startTimeMillis, TimeUnit.MILLISECONDS) - .setAttribute(SemanticAttributes.MESSAGING_SYSTEM, "rabbitmq") - .setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, "queue") - .setAttribute(SemanticAttributes.MESSAGING_OPERATION, "process") - .startSpan(); - onDeliver(span, envelope); - - if (body != null) { - span.setAttribute( - SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES, (long) body.length); - } - if (properties.getTimestamp() != null) { - // this will be set if the sender sets the timestamp, - // or if a plugin is installed on the rabbitmq broker - long produceTime = properties.getTimestamp().getTime(); - long consumeTime = NANOSECONDS.toMillis(startTimeMillis); - span.setAttribute("record.queue_time_ms", Math.max(0L, consumeTime - produceTime)); - } - - return span; - } - - public void onPublish(Span span, String exchange, String routingKey) { - String exchangeName = normalizeExchangeName(exchange); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, exchangeName); - String routing = - routingKey == null || routingKey.isEmpty() - ? "" - : routingKey.startsWith("amq.gen-") ? "" : routingKey; - span.updateName(exchangeName + " -> " + routing + " send"); - span.setAttribute("amqp.command", "basic.publish"); - if (routingKey != null && !routingKey.isEmpty()) { - span.setAttribute("messaging.rabbitmq.routing_key", routingKey); - span.setAttribute("amqp.routing_key", routingKey); - } - } - - public String spanNameOnGet(String queue) { - return (queue.startsWith("amq.gen-") ? "" : queue) + " receive"; - } - - public void onGet(Span span, String queue) { - span.setAttribute("amqp.command", "basic.get"); - span.setAttribute("amqp.queue", queue); - } - - public String spanNameOnDeliver(String queue) { - if (queue == null || queue.isEmpty()) { - return " process"; - } else if (queue.startsWith("amq.gen-")) { - return " process"; - } else { - return queue + " process"; - } - } - - public void onDeliver(Span span, Envelope envelope) { - span.setAttribute("amqp.command", "basic.deliver"); - - if (envelope != null) { - String exchange = envelope.getExchange(); - span.setAttribute(SemanticAttributes.MESSAGING_DESTINATION, normalizeExchangeName(exchange)); - String routingKey = envelope.getRoutingKey(); - if (routingKey != null && !routingKey.isEmpty()) { - span.setAttribute("messaging.rabbitmq.routing_key", routingKey); - } - } - } - - private String normalizeExchangeName(String exchange) { - return exchange == null || exchange.isEmpty() ? "" : exchange; - } - - public void onCommand(Span span, Command command) { - String name = command.getMethod().protocolMethodName(); - - if (!name.equals("basic.publish")) { - span.updateName(name); - } - span.setAttribute("amqp.command", name); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.rabbitmq"; - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TextMapExtractAdapter.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TextMapExtractAdapter.java deleted file mode 100644 index 98ccba4ffd..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TextMapExtractAdapter.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.util.Map; - -public class TextMapExtractAdapter implements TextMapPropagator.Getter> { - - public static final TextMapExtractAdapter GETTER = new TextMapExtractAdapter(); - - @Override - public Iterable keys(Map carrier) { - return carrier.keySet(); - } - - @Override - public String get(Map carrier, String key) { - Object obj = carrier.get(key); - return obj == null ? null : obj.toString(); - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TextMapInjectAdapter.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TextMapInjectAdapter.java deleted file mode 100644 index 64fa9c5331..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TextMapInjectAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.util.Map; - -public class TextMapInjectAdapter implements TextMapPropagator.Setter> { - - public static final TextMapInjectAdapter SETTER = new TextMapInjectAdapter(); - - @Override - public void set(Map carrier, String key, String value) { - carrier.put(key, value); - } -} diff --git a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TracedDelegatingConsumer.java b/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TracedDelegatingConsumer.java deleted file mode 100644 index e488260da5..0000000000 --- a/instrumentation/rabbitmq-2.7/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/TracedDelegatingConsumer.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rabbitmq; - -import static io.opentelemetry.javaagent.instrumentation.rabbitmq.RabbitTracer.tracer; - -import com.rabbitmq.client.AMQP; -import com.rabbitmq.client.Consumer; -import com.rabbitmq.client.Envelope; -import com.rabbitmq.client.ShutdownSignalException; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import java.io.IOException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Wrapping the consumer instead of instrumenting it directly because it doesn't get access to the - * queue name when the message is consumed. - */ -public class TracedDelegatingConsumer implements Consumer { - - private static final Logger log = LoggerFactory.getLogger(TracedDelegatingConsumer.class); - - private final String queue; - private final Consumer delegate; - - public TracedDelegatingConsumer(String queue, Consumer delegate) { - this.queue = queue; - this.delegate = delegate; - } - - @Override - public void handleConsumeOk(String consumerTag) { - delegate.handleConsumeOk(consumerTag); - } - - @Override - public void handleCancelOk(String consumerTag) { - delegate.handleCancelOk(consumerTag); - } - - @Override - public void handleCancel(String consumerTag) throws IOException { - delegate.handleCancel(consumerTag); - } - - @Override - public void handleShutdownSignal(String consumerTag, ShutdownSignalException sig) { - delegate.handleShutdownSignal(consumerTag, sig); - } - - @Override - public void handleRecoverOk(String consumerTag) { - delegate.handleRecoverOk(consumerTag); - } - - @Override - public void handleDelivery( - String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) - throws IOException { - Span span = null; - Scope scope = null; - try { - span = tracer().startDeliverySpan(queue, envelope, properties, body); - scope = tracer().startScope(span); - - } catch (Exception e) { - log.debug("Instrumentation error in tracing consumer", e); - } finally { - // TODO this is very unusual code structure for this repo - // We have to review it - try { - // Call delegate. - delegate.handleDelivery(consumerTag, envelope, properties, body); - - if (span != null) { - tracer().end(span); - } - } catch (Throwable throwable) { - if (span != null) { - tracer().endExceptionally(span, throwable); - } - - throw throwable; - } finally { - if (scope != null) { - scope.close(); - } - } - } - } -} diff --git a/instrumentation/rabbitmq-2.7/src/test/groovy/RabbitMQTest.groovy b/instrumentation/rabbitmq-2.7/src/test/groovy/RabbitMQTest.groovy deleted file mode 100644 index 72b7a89401..0000000000 --- a/instrumentation/rabbitmq-2.7/src/test/groovy/RabbitMQTest.groovy +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.CONSUMER -import static io.opentelemetry.api.trace.Span.Kind.PRODUCER -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import com.rabbitmq.client.AMQP -import com.rabbitmq.client.Channel -import com.rabbitmq.client.Connection -import com.rabbitmq.client.ConnectionFactory -import com.rabbitmq.client.Consumer -import com.rabbitmq.client.DefaultConsumer -import com.rabbitmq.client.Envelope -import com.rabbitmq.client.GetResponse -import com.rabbitmq.client.ShutdownSignalException -import io.opentelemetry.api.common.AttributeKey -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.sdk.trace.data.SpanData -import java.time.Duration -import org.springframework.amqp.core.AmqpAdmin -import org.springframework.amqp.core.AmqpTemplate -import org.springframework.amqp.core.Queue -import org.springframework.amqp.rabbit.connection.CachingConnectionFactory -import org.springframework.amqp.rabbit.core.RabbitAdmin -import org.springframework.amqp.rabbit.core.RabbitTemplate -import org.testcontainers.containers.GenericContainer -import spock.lang.Shared - -class RabbitMQTest extends AgentTestRunner { - - @Shared - def rabbitMQContainer - @Shared - InetSocketAddress rabbitmqAddress - - ConnectionFactory factory = new ConnectionFactory(host: rabbitmqAddress.hostName, port: rabbitmqAddress.port) - Connection conn = factory.newConnection() - Channel channel = conn.createChannel() - - def setupSpec() { - rabbitMQContainer = new GenericContainer('rabbitmq:latest') - .withExposedPorts(5672) - .withStartupTimeout(Duration.ofSeconds(120)) - rabbitMQContainer.start() - rabbitmqAddress = new InetSocketAddress( - rabbitMQContainer.containerIpAddress, - rabbitMQContainer.getMappedPort(5672) - ) - } - - def cleanupSpec() { - if (rabbitMQContainer) { - rabbitMQContainer.stop() - } - } - - def cleanup() { - try { - channel.close() - conn.close() - } catch (ShutdownSignalException ignored) { - } - } - - def "test rabbit publish/get"() { - setup: - GetResponse response = runUnderTrace("parent") { - channel.exchangeDeclare(exchangeName, "direct", false) - String queueName = channel.queueDeclare().getQueue() - channel.queueBind(queueName, exchangeName, routingKey) - channel.basicPublish(exchangeName, routingKey, null, "Hello, world!".getBytes()) - return channel.basicGet(queueName, true) - } - - expect: - new String(response.getBody()) == "Hello, world!" - - and: - assertTraces(1) { - trace(0, 6) { - span(0) { - name "parent" - attributes { - } - } - rabbitSpan(it, 1, null, null, null, "exchange.declare", span(0)) - rabbitSpan(it, 2, null, null, null, "queue.declare", span(0)) - rabbitSpan(it, 3, null, null, null, "queue.bind", span(0)) - rabbitSpan(it, 4, exchangeName, routingKey, "send", "$exchangeName -> $routingKey", span(0)) - rabbitSpan(it, 5, exchangeName, routingKey, "receive", "", span(0)) - } - } - - where: - exchangeName | routingKey - "some-exchange" | "some-routing-key" - } - - def "test rabbit publish/get default exchange"() { - setup: - String queueName = channel.queueDeclare().getQueue() - channel.basicPublish("", queueName, null, "Hello, world!".getBytes()) - GetResponse response = channel.basicGet(queueName, true) - - expect: - new String(response.getBody()) == "Hello, world!" - - and: - assertTraces(3) { - trace(0, 1) { - rabbitSpan(it, 0, null, null, null, "queue.declare") - } - trace(1, 1) { - rabbitSpan(it, 0, "", null, "send", " -> ") - } - trace(2, 1) { - rabbitSpan(it, 0, "", null, "receive", "", null) - } - } - } - - def "test rabbit consume #messageCount messages"() { - setup: - channel.exchangeDeclare(exchangeName, "direct", false) - String queueName = (messageCount % 2 == 0) ? - channel.queueDeclare().getQueue() : - channel.queueDeclare("some-queue", false, true, true, null).getQueue() - channel.queueBind(queueName, exchangeName, "") - - def deliveries = [] - - Consumer callback = new DefaultConsumer(channel) { - @Override - void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { - deliveries << new String(body) - } - } - - channel.basicConsume(queueName, callback) - - (1..messageCount).each { - if (setTimestamp) { - channel.basicPublish(exchangeName, "", - new AMQP.BasicProperties.Builder().timestamp(new Date()).build(), - "msg $it".getBytes()) - } else { - channel.basicPublish(exchangeName, "", null, "msg $it".getBytes()) - } - } - def resource = messageCount % 2 == 0 ? "" : queueName - - expect: - assertTraces(4 + messageCount) { - trace(0, 1) { - rabbitSpan(it, null, null, null, "exchange.declare") - } - trace(1, 1) { - rabbitSpan(it, null, null, null, "queue.declare") - } - trace(2, 1) { - rabbitSpan(it, null, null, null, "queue.bind") - } - trace(3, 1) { - rabbitSpan(it, null, null, null, "basic.consume") - } - (1..messageCount).each { - trace(3 + it, 2) { - rabbitSpan(it, 0, exchangeName, null, "send", "$exchangeName -> ") - rabbitSpan(it, 1, exchangeName, null, "process", resource, span(0), null, null, null, setTimestamp) - } - } - } - - deliveries == (1..messageCount).collect { "msg $it" } - - where: - exchangeName | messageCount | setTimestamp - "some-exchange" | 1 | false - "some-exchange" | 2 | false - "some-exchange" | 3 | false - "some-exchange" | 4 | false - "some-exchange" | 1 | true - "some-exchange" | 2 | true - "some-exchange" | 3 | true - "some-exchange" | 4 | true - } - - def "test rabbit consume error"() { - setup: - def error = new FileNotFoundException("Message Error") - channel.exchangeDeclare(exchangeName, "direct", false) - String queueName = channel.queueDeclare().getQueue() - channel.queueBind(queueName, exchangeName, "") - - Consumer callback = new DefaultConsumer(channel) { - @Override - void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { - throw error - // Unfortunately this doesn't seem to be observable in the test outside of the span generated. - } - } - - channel.basicConsume(queueName, callback) - - channel.basicPublish(exchangeName, "", null, "msg".getBytes()) - - expect: - assertTraces(5) { - trace(0, 1) { - rabbitSpan(it, null, null, null, "exchange.declare") - } - trace(1, 1) { - rabbitSpan(it, null, null, null, "queue.declare") - } - trace(2, 1) { - rabbitSpan(it, null, null, null, "queue.bind") - } - trace(3, 1) { - rabbitSpan(it, null, null, null, "basic.consume") - } - trace(4, 2) { - rabbitSpan(it, 0, exchangeName, null, "send", "$exchangeName -> ") - rabbitSpan(it, 1, exchangeName, null, "process", "", span(0), null, error, error.message) - } - } - - where: - exchangeName = "some-error-exchange" - } - - def "test rabbit error (#command)"() { - when: - closure.call(channel) - - then: - def throwable = thrown(exception) - - and: - - assertTraces(1) { - trace(0, 1) { - rabbitSpan(it, null, null, operation, command, null, null, throwable, errorMsg) - } - } - - where: - command | exception | errorMsg | operation | closure - "exchange.declare" | IOException | null | null | { - it.exchangeDeclare("some-exchange", "invalid-type", true) - } - "Channel.basicConsume" | IllegalStateException | "Invalid configuration: 'queue' must be non-null." | null | { - it.basicConsume(null, null) - } - "" | IOException | null | "receive" | { - it.basicGet("amq.gen-invalid-channel", true) - } - } - - def "test spring rabbit"() { - setup: - def connectionFactory = new CachingConnectionFactory(rabbitmqAddress.hostName, rabbitmqAddress.port) - AmqpAdmin admin = new RabbitAdmin(connectionFactory) - def queue = new Queue("some-routing-queue", false, true, true, null) - admin.declareQueue(queue) - AmqpTemplate template = new RabbitTemplate(connectionFactory) - template.convertAndSend(queue.name, "foo") - String message = (String) template.receiveAndConvert(queue.name) - - expect: - message == "foo" - - and: - assertTraces(3) { - trace(0, 1) { - rabbitSpan(it, null, null, null, "queue.declare") - } - trace(1, 1) { - rabbitSpan(it, 0, "", "some-routing-queue", "send", " -> some-routing-queue") - } - trace(2, 1) { - rabbitSpan(it, 0, "", "some-routing-queue", "receive", queue.name, null) - } - } - } - - def rabbitSpan( - TraceAssert trace, - String exchange, - String routingKey, - String operation, - String resource, - Object parentSpan = null, - Object linkSpan = null, - Throwable exception = null, - String errorMsg = null, - Boolean expectTimestamp = false - ) { - rabbitSpan(trace, 0, exchange, routingKey, operation, resource, parentSpan, linkSpan, exception, errorMsg, expectTimestamp) - } - - def rabbitSpan( - TraceAssert trace, - int index, - String exchange, - String routingKey, - String operation, - String resource, - Object parentSpan = null, - Object linkSpan = null, - Throwable exception = null, - String errorMsg = null, - Boolean expectTimestamp = false - ) { - - def spanName = resource - if (operation != null) { - spanName = spanName + " " + operation - } - - trace.span(index) { - name spanName - - switch (trace.span(index).attributes.get(AttributeKey.stringKey("amqp.command"))) { - case "basic.publish": - kind PRODUCER - break - case "basic.get": - kind CLIENT - break - case "basic.deliver": - kind CONSUMER - break - default: - kind CLIENT - } - - if (parentSpan) { - childOf((SpanData) parentSpan) - } else { - hasNoParent() - } - - if (linkSpan) { - hasLink((SpanData) linkSpan) - } - - errored exception != null - if (exception) { - errorEvent(exception.class, errorMsg) - } - - attributes { - "${SemanticAttributes.NET_PEER_NAME.key}" { it == null || it instanceof String } - "${SemanticAttributes.NET_PEER_IP.key}" { "127.0.0.1" } - "${SemanticAttributes.NET_PEER_PORT.key}" { it == null || it instanceof Long } - - "${SemanticAttributes.MESSAGING_SYSTEM.key}" "rabbitmq" - "${SemanticAttributes.MESSAGING_DESTINATION.key}" exchange - "${SemanticAttributes.MESSAGING_DESTINATION_KIND.key}" "queue" - //TODO add to SemanticAttributes - "messaging.rabbitmq.routing_key" { it == null || it == routingKey || it.startsWith("amq.gen-") } - if (operation != null && operation != "send") { - "${SemanticAttributes.MESSAGING_OPERATION.key}" operation - } - if (expectTimestamp) { - "record.queue_time_ms" { it instanceof Long && it >= 0 } - } - - switch (attribute("amqp.command")) { - case "basic.publish": - "amqp.command" "basic.publish" - "amqp.routing_key" { - it == null || it == "some-routing-key" || it == "some-routing-queue" || it.startsWith("amq.gen-") - } - "amqp.delivery_mode" { it == null || it == 2 } - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - break - case "basic.get": - "amqp.command" "basic.get" - //TODO why this queue name is not a destination for semantic convention - "amqp.queue" { it == "some-queue" || it == "some-routing-queue" || it.startsWith("amq.gen-") } - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" { it == null || it instanceof Long } - break - case "basic.deliver": - "amqp.command" "basic.deliver" - "${SemanticAttributes.MESSAGING_MESSAGE_PAYLOAD_SIZE_BYTES.key}" Long - break - default: - "amqp.command" { it == null || it == resource } - } - } - } - } -} diff --git a/instrumentation/ratpack-1.4/javaagent/src/test/groovy/RatpackOtherTest.groovy b/instrumentation/ratpack-1.4/javaagent/src/test/groovy/RatpackOtherTest.groovy index 0850edd18c..b6a8997e7e 100644 --- a/instrumentation/ratpack-1.4/javaagent/src/test/groovy/RatpackOtherTest.groovy +++ b/instrumentation/ratpack-1.4/javaagent/src/test/groovy/RatpackOtherTest.groovy @@ -6,9 +6,9 @@ import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.api.trace.Span.Kind.SERVER +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.OkHttpUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import okhttp3.HttpUrl import okhttp3.OkHttpClient import okhttp3.Request diff --git a/instrumentation/ratpack-1.4/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy b/instrumentation/ratpack-1.4/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy index f72f7c6bb0..ee9bbc94be 100644 --- a/instrumentation/ratpack-1.4/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy +++ b/instrumentation/ratpack-1.4/javaagent/src/test/groovy/server/RatpackHttpServerTest.groovy @@ -5,13 +5,13 @@ package server +import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL import io.opentelemetry.instrumentation.test.asserts.TraceAssert import io.opentelemetry.instrumentation.test.base.HttpServerTest diff --git a/instrumentation/ratpack-1.4/ratpack-1.4.gradle b/instrumentation/ratpack-1.4/ratpack-1.4.gradle deleted file mode 100644 index 3b26033a5f..0000000000 --- a/instrumentation/ratpack-1.4/ratpack-1.4.gradle +++ /dev/null @@ -1,21 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.ratpack" - module = 'ratpack-core' - versions = "[1.4.0,)" - skipVersions += ["0.9.12", "0.9.13", "0.9.14",] - } -} - -dependencies { - library group: 'io.ratpack', name: 'ratpack-core', version: '1.4.0' - - implementation project(':instrumentation:netty:netty-4.1') - - testLibrary group: 'io.ratpack', name: 'ratpack-groovy-test', version: '1.4.0' - if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { - testImplementation group: 'com.sun.activation', name: 'jakarta.activation', version: '1.2.2' - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ActionWrapper.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ActionWrapper.java deleted file mode 100644 index 76edd7d3b6..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ActionWrapper.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ratpack.func.Action; - -public class ActionWrapper implements Action { - - private static final Logger log = LoggerFactory.getLogger(ActionWrapper.class); - - private final Action delegate; - private final Context parentContext; - - private ActionWrapper(Action delegate, Context parentContext) { - assert parentContext != null; - this.delegate = delegate; - this.parentContext = parentContext; - } - - @Override - public void execute(T t) throws Exception { - try (Scope ignored = parentContext.makeCurrent()) { - delegate.execute(t); - } - } - - public static Action wrapIfNeeded(Action delegate) { - if (delegate instanceof ActionWrapper) { - return delegate; - } - log.debug("Wrapping action task {}", delegate); - return new ActionWrapper(delegate, Context.current()); - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/BlockWrapper.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/BlockWrapper.java deleted file mode 100644 index d937f7c997..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/BlockWrapper.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ratpack.func.Block; - -public class BlockWrapper implements Block { - - private static final Logger log = LoggerFactory.getLogger(BlockWrapper.class); - - private static final Tracer TRACER = - OpenTelemetry.getGlobalTracer("io.opentelemetry.auto.ratpack-1.4"); - - private final Block delegate; - private final Context parentContext; - - private BlockWrapper(Block delegate, Context parentContext) { - assert parentContext != null; - this.delegate = delegate; - this.parentContext = parentContext; - } - - @Override - public void execute() throws Exception { - try (Scope ignored = parentContext.makeCurrent()) { - delegate.execute(); - } - } - - public static Block wrapIfNeeded(Block delegate) { - if (delegate instanceof BlockWrapper) { - return delegate; - } - log.debug("Wrapping block {}", delegate); - return new BlockWrapper(delegate, Context.current()); - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java deleted file mode 100644 index e7fed1420d..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ContinuationInstrumentation.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import ratpack.func.Block; - -public class ContinuationInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("ratpack.exec.internal.Continuation"); - } - - @Override - public ElementMatcher typeMatcher() { - return nameStartsWith("ratpack.exec.") - .and(implementsInterface(named("ratpack.exec.internal.Continuation"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("resume").and(takesArgument(0, named("ratpack.func.Block"))), - ContinuationInstrumentation.class.getName() + "$ResumeAdvice"); - } - - public static class ResumeAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void wrap(@Advice.Argument(value = 0, readOnly = false) Block block) { - block = BlockWrapper.wrapIfNeeded(block); - } - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java deleted file mode 100644 index 290c91393b..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/DefaultExecutionInstrumentation.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import ratpack.exec.internal.Continuation; -import ratpack.func.Action; - -public class DefaultExecutionInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("ratpack.exec.internal.DefaultExecution"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - nameStartsWith("delimit") // include delimitStream - .and(takesArgument(0, named("ratpack.func.Action"))) - .and(takesArgument(1, named("ratpack.func.Action"))), - DefaultExecutionInstrumentation.class.getName() + "$DelimitAdvice"); - } - - public static class DelimitAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void wrap( - @Advice.Argument(value = 0, readOnly = false) Action onError, - @Advice.Argument(value = 1, readOnly = false) Action segment) { - onError = ActionWrapper.wrapIfNeeded(onError); - segment = ActionWrapper.wrapIfNeeded(segment); - } - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ErrorHandlerAdvice.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ErrorHandlerAdvice.java deleted file mode 100644 index e44bd9a6ea..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ErrorHandlerAdvice.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackTracer.tracer; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.StatusCode; -import java.util.Optional; -import net.bytebuddy.asm.Advice; -import ratpack.handling.Context; - -public class ErrorHandlerAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void captureThrowable( - @Advice.Argument(0) Context ctx, @Advice.Argument(1) Throwable throwable) { - Optional span = ctx.maybeGet(Span.class); - if (span.isPresent()) { - // TODO this emulates old behaviour of BaseDecorator. Has to review - span.get().setStatus(StatusCode.ERROR); - tracer().addThrowable(span.get(), throwable); - } - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackInstrumentationModule.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackInstrumentationModule.java deleted file mode 100644 index 59ab2bfdaa..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackInstrumentationModule.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static java.util.Arrays.asList; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; - -@AutoService(InstrumentationModule.class) -public class RatpackInstrumentationModule extends InstrumentationModule { - public RatpackInstrumentationModule() { - super("ratpack", "ratpack-1.4"); - } - - @Override - public List typeInstrumentations() { - return asList( - new ContinuationInstrumentation(), - new DefaultExecutionInstrumentation(), - new ServerErrorHandlerInstrumentation(), - new ServerRegistryInstrumentation()); - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackTracer.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackTracer.java deleted file mode 100644 index e986e79b28..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/RatpackTracer.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import ratpack.handling.Context; - -public class RatpackTracer extends BaseTracer { - private static final RatpackTracer TRACER = new RatpackTracer(); - - public static RatpackTracer tracer() { - return TRACER; - } - - public Span onContext(Span span, Context ctx) { - String description = ctx.getPathBinding().getDescription(); - if (description == null || description.isEmpty()) { - description = "/"; - } else if (!description.startsWith("/")) { - description = "/" + description; - } - - span.updateName(description); - - return span; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.ratpack"; - } - - @Override - protected Throwable unwrapThrowable(Throwable throwable) { - if (throwable instanceof Error && throwable.getCause() != null) { - return throwable.getCause(); - } else { - return throwable; - } - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java deleted file mode 100644 index 388fa81680..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerErrorHandlerInstrumentation.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isAbstract; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class ServerErrorHandlerInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("ratpack.error.ServerErrorHandler"); - } - - @Override - public ElementMatcher typeMatcher() { - return not(isAbstract()).and(implementsInterface(named("ratpack.error.ServerErrorHandler"))); - } - - @Override - public Map, String> transformers() { - return singletonMap( - named("error") - .and(takesArgument(0, named("ratpack.handling.Context"))) - .and(takesArgument(1, Throwable.class)), - ErrorHandlerAdvice.class.getName()); - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryAdvice.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryAdvice.java deleted file mode 100644 index 6447e291bd..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryAdvice.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import net.bytebuddy.asm.Advice; -import ratpack.handling.HandlerDecorator; -import ratpack.registry.Registry; - -public class ServerRegistryAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void injectTracing(@Advice.Return(readOnly = false) Registry registry) { - registry = - registry.join( - Registry.builder().add(HandlerDecorator.prepend(TracingHandler.INSTANCE)).build()); - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java deleted file mode 100644 index fe91ddb0da..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/ServerRegistryInstrumentation.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -public class ServerRegistryInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return named("ratpack.server.internal.ServerRegistry"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isStatic()).and(named("buildBaseRegistry")), - ServerRegistryAdvice.class.getName()); - } -} diff --git a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/TracingHandler.java b/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/TracingHandler.java deleted file mode 100644 index 5ce3a9755f..0000000000 --- a/instrumentation/ratpack-1.4/src/main/java/io/opentelemetry/javaagent/instrumentation/ratpack/TracingHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.ratpack; - -import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackTracer.tracer; - -import io.netty.util.Attribute; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Span.Kind; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys; -import ratpack.handling.Context; -import ratpack.handling.Handler; - -public final class TracingHandler implements Handler { - public static final Handler INSTANCE = new TracingHandler(); - - @Override - public void handle(Context ctx) { - Attribute spanAttribute = - ctx.getDirectChannelAccess().getChannel().attr(AttributeKeys.SERVER_SPAN); - io.opentelemetry.context.Context serverSpanContext = spanAttribute.get(); - - // Relying on executor instrumentation to assume the netty span is in context as the parent. - Span ratpackSpan = tracer().startSpan("ratpack.handler", Kind.INTERNAL); - ctx.getExecution().add(ratpackSpan); - - ctx.getResponse() - .beforeSend( - response -> { - if (serverSpanContext != null) { - // Rename the netty span name with the ratpack route. - tracer().onContext(Span.fromContext(serverSpanContext), ctx); - } - tracer().onContext(ratpackSpan, ctx); - tracer().end(ratpackSpan); - }); - - try (Scope ignored = ratpackSpan.makeCurrent()) { - ctx.next(); - // exceptions are captured by ServerErrorHandlerInstrumentation - } - } -} diff --git a/instrumentation/ratpack-1.4/src/test/groovy/RatpackOtherTest.groovy b/instrumentation/ratpack-1.4/src/test/groovy/RatpackOtherTest.groovy deleted file mode 100644 index b6a8997e7e..0000000000 --- a/instrumentation/ratpack-1.4/src/test/groovy/RatpackOtherTest.groovy +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.api.trace.Span.Kind.SERVER - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.OkHttpUtils -import okhttp3.HttpUrl -import okhttp3.OkHttpClient -import okhttp3.Request -import ratpack.groovy.test.embed.GroovyEmbeddedApp -import ratpack.path.PathBinding - -class RatpackOtherTest extends AgentTestRunner { - - OkHttpClient client = OkHttpUtils.client() - - def "test bindings for #path"() { - setup: - def app = GroovyEmbeddedApp.ratpack { - handlers { - prefix("a") { - all { - context.render(context.get(PathBinding).description) - } - } - prefix("b/::\\d+") { - all { - context.render(context.get(PathBinding).description) - } - } - prefix("c/:val?") { - all { - context.render(context.get(PathBinding).description) - } - } - prefix("d/:val") { - all { - context.render(context.get(PathBinding).description) - } - } - prefix("e/:val?:\\d+") { - all { - context.render(context.get(PathBinding).description) - } - } - prefix("f/:val:\\d+") { - all { - context.render(context.get(PathBinding).description) - } - } - } - } - def request = new Request.Builder() - .url(HttpUrl.get(app.address).newBuilder().addPathSegments(path).build()) - .get() - .build() - - when: - def resp = client.newCall(request).execute() - - then: - resp.code() == 200 - resp.body.string() == route - - assertTraces(1) { - trace(0, 2) { - span(0) { - name "/$route" - kind SERVER - hasNoParent() - errored false - attributes { - "${SemanticAttributes.NET_PEER_IP.key()}" "127.0.0.1" - "${SemanticAttributes.NET_PEER_PORT.key()}" Long - "${SemanticAttributes.HTTP_URL.key()}" "${app.address.resolve(path)}" - "${SemanticAttributes.HTTP_METHOD.key()}" "GET" - "${SemanticAttributes.HTTP_STATUS_CODE.key()}" 200 - "${SemanticAttributes.HTTP_FLAVOR.key()}" "HTTP/1.1" - "${SemanticAttributes.HTTP_USER_AGENT.key()}" String - "${SemanticAttributes.HTTP_CLIENT_IP.key()}" "127.0.0.1" - } - } - span(1) { - name "/$route" - kind INTERNAL - childOf span(0) - errored false - attributes { - } - } - } - } - - where: - path | route - "a" | "a" - "b/123" | "b/::\\d+" - "c" | "c/:val?" - "c/123" | "c/:val?" - "c/foo" | "c/:val?" - "d/123" | "d/:val" - "d/foo" | "d/:val" - "e" | "e/:val?:\\d+" - "e/123" | "e/:val?:\\d+" - "e/foo" | "e/:val?:\\d+" - "f/123" | "f/:val:\\d+" - } -} diff --git a/instrumentation/ratpack-1.4/src/test/groovy/client/RatpackForkedHttpClientTest.groovy b/instrumentation/ratpack-1.4/src/test/groovy/client/RatpackForkedHttpClientTest.groovy deleted file mode 100644 index c33acb7f27..0000000000 --- a/instrumentation/ratpack-1.4/src/test/groovy/client/RatpackForkedHttpClientTest.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package client - - -import ratpack.exec.ExecResult - -class RatpackForkedHttpClientTest extends RatpackHttpClientTest { - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - ExecResult result = exec.yield { - def resp = client.request(uri) { spec -> - spec.method(method) - spec.headers { headersSpec -> - headers.entrySet().each { - headersSpec.add(it.key, it.value) - } - } - } - return resp.fork().map { - callback?.call() - it.status.code - } - } - return result.value - } -} diff --git a/instrumentation/ratpack-1.4/src/test/groovy/client/RatpackHttpClientTest.groovy b/instrumentation/ratpack-1.4/src/test/groovy/client/RatpackHttpClientTest.groovy deleted file mode 100644 index 083a2a917d..0000000000 --- a/instrumentation/ratpack-1.4/src/test/groovy/client/RatpackHttpClientTest.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package client - -import io.opentelemetry.instrumentation.test.base.HttpClientTest -import java.time.Duration -import ratpack.exec.ExecResult -import ratpack.http.client.HttpClient -import ratpack.test.exec.ExecHarness -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Timeout - -@Timeout(5) -class RatpackHttpClientTest extends HttpClientTest { - - @AutoCleanup - @Shared - ExecHarness exec = ExecHarness.harness() - - @Shared - def client = HttpClient.of { - it.readTimeout(Duration.ofSeconds(2)) - // Connect timeout added in 1.5 - } - - @Override - int doRequest(String method, URI uri, Map headers, Closure callback) { - ExecResult result = exec.yield { - def resp = client.request(uri) { spec -> - spec.connectTimeout(Duration.ofSeconds(2)) - spec.method(method) - spec.headers { headersSpec -> - headers.entrySet().each { - headersSpec.add(it.key, it.value) - } - } - } - return resp.map { - callback?.call() - it.status.code - } - } - return result.value - } - - @Override - boolean testRedirects() { - false - } - - @Override - boolean testConnectionFailure() { - false - } - - @Override - boolean testRemoteConnection() { - return false - } -} diff --git a/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackAsyncHttpServerTest.groovy b/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackAsyncHttpServerTest.groovy deleted file mode 100644 index 560e44bd31..0000000000 --- a/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackAsyncHttpServerTest.groovy +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import ratpack.exec.Promise -import ratpack.groovy.test.embed.GroovyEmbeddedApp -import ratpack.test.embed.EmbeddedApp - -class RatpackAsyncHttpServerTest extends RatpackHttpServerTest { - - @Override - EmbeddedApp startServer(int bindPort) { - def ratpack = GroovyEmbeddedApp.ratpack { - serverConfig { - port bindPort - address InetAddress.getByName('localhost') - } - bindings { - bind TestErrorHandler - } - handlers { - prefix(SUCCESS.rawPath()) { - all { - Promise.sync { - SUCCESS - } then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(endpoint.body) - } - } - } - } - prefix(QUERY_PARAM.rawPath()) { - all { - Promise.sync { - QUERY_PARAM - } then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(request.query) - } - } - } - } - prefix(REDIRECT.rawPath()) { - all { - Promise.sync { - REDIRECT - } then { endpoint -> - controller(endpoint) { - context.redirect(endpoint.body) - } - } - } - } - prefix(ERROR.rawPath()) { - all { - Promise.sync { - ERROR - } then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(endpoint.body) - } - } - } - } - prefix(EXCEPTION.rawPath()) { - all { - Promise.sync { - EXCEPTION - } then { endpoint -> - controller(endpoint) { - throw new Exception(endpoint.body) - } - } - } - } - prefix("path/:id/param") { - all { - Promise.sync { - PATH_PARAM - }.fork().then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(pathTokens.id) - } - } - } - } - } - } - ratpack.server.start() - - assert ratpack.address.port == bindPort - assert ratpack.server.bindHost == 'localhost' - return ratpack - } -} diff --git a/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackForkedHttpServerTest.groovy b/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackForkedHttpServerTest.groovy deleted file mode 100644 index 706a6c98b1..0000000000 --- a/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackForkedHttpServerTest.groovy +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import ratpack.exec.Promise -import ratpack.groovy.test.embed.GroovyEmbeddedApp -import ratpack.test.embed.EmbeddedApp - -class RatpackForkedHttpServerTest extends RatpackHttpServerTest { - - @Override - EmbeddedApp startServer(int bindPort) { - def ratpack = GroovyEmbeddedApp.ratpack { - serverConfig { - port bindPort - address InetAddress.getByName('localhost') - } - bindings { - bind TestErrorHandler - } - handlers { - prefix(SUCCESS.rawPath()) { - all { - Promise.sync { - SUCCESS - }.fork().then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(endpoint.body) - } - } - } - } - prefix(QUERY_PARAM.rawPath()) { - all { - Promise.sync { - QUERY_PARAM - }.fork().then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(request.query) - } - } - } - } - prefix(REDIRECT.rawPath()) { - all { - Promise.sync { - REDIRECT - }.fork().then { endpoint -> - controller(endpoint) { - context.redirect(endpoint.body) - } - } - } - } - prefix(ERROR.rawPath()) { - all { - Promise.sync { - ERROR - }.fork().then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(endpoint.body) - } - } - } - } - prefix(EXCEPTION.rawPath()) { - all { - Promise.sync { - EXCEPTION - }.fork().then { endpoint -> - controller(endpoint) { - throw new Exception(endpoint.body) - } - } - } - } - prefix("path/:id/param") { - all { - Promise.sync { - PATH_PARAM - }.fork().then { endpoint -> - controller(endpoint) { - context.response.status(endpoint.status).send(pathTokens.id) - } - } - } - } - } - } - ratpack.server.start() - - assert ratpack.address.port == bindPort - return ratpack - } -} diff --git a/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackHttpServerTest.groovy b/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackHttpServerTest.groovy deleted file mode 100644 index ee9bbc94be..0000000000 --- a/instrumentation/ratpack-1.4/src/test/groovy/server/RatpackHttpServerTest.groovy +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package server - -import static io.opentelemetry.api.trace.Span.Kind.INTERNAL -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.ERROR -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.EXCEPTION -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.PATH_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.QUERY_PARAM -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.REDIRECT -import static io.opentelemetry.instrumentation.test.base.HttpServerTest.ServerEndpoint.SUCCESS - -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTest -import io.opentelemetry.sdk.trace.data.SpanData -import ratpack.error.ServerErrorHandler -import ratpack.groovy.test.embed.GroovyEmbeddedApp -import ratpack.handling.Context -import ratpack.test.embed.EmbeddedApp - -class RatpackHttpServerTest extends HttpServerTest { - - @Override - EmbeddedApp startServer(int bindPort) { - def ratpack = GroovyEmbeddedApp.ratpack { - serverConfig { - port bindPort - address InetAddress.getByName('localhost') - } - bindings { - bind TestErrorHandler - } - handlers { - prefix(SUCCESS.rawPath()) { - all { - controller(SUCCESS) { - context.response.status(SUCCESS.status).send(SUCCESS.body) - } - } - } - prefix(QUERY_PARAM.rawPath()) { - all { - controller(QUERY_PARAM) { - context.response.status(QUERY_PARAM.status).send(request.query) - } - } - } - prefix(REDIRECT.rawPath()) { - all { - controller(REDIRECT) { - context.redirect(REDIRECT.body) - } - } - } - prefix(ERROR.rawPath()) { - all { - controller(ERROR) { - context.response.status(ERROR.status).send(ERROR.body) - } - } - } - prefix(EXCEPTION.rawPath()) { - all { - controller(EXCEPTION) { - throw new Exception(EXCEPTION.body) - } - } - } - prefix("path/:id/param") { - all { - controller(PATH_PARAM) { - context.response.status(PATH_PARAM.status).send(pathTokens.id) - } - } - } - } - } - ratpack.server.start() - - assert ratpack.address.port == bindPort - return ratpack - } - - static class TestErrorHandler implements ServerErrorHandler { - @Override - void error(Context context, Throwable throwable) throws Exception { - context.response.status(500).send(throwable.message) - } - } - - @Override - void stopServer(EmbeddedApp server) { - server.close() - } - - @Override - boolean hasHandlerSpan() { - true - } - - @Override - boolean testPathParam() { - true - } - - @Override - void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint = SUCCESS) { - trace.span(index) { - name endpoint.status == 404 ? "/" : endpoint == PATH_PARAM ? "/path/:id/param" : endpoint.path - kind INTERNAL - errored endpoint == EXCEPTION - childOf((SpanData) parent) - if (endpoint == EXCEPTION) { - errorEvent(Exception, EXCEPTION.body) - } - } - } - - @Override - String expectedServerSpanName(ServerEndpoint endpoint) { - return endpoint.status == 404 ? "/" : endpoint == PATH_PARAM ? "/path/:id/param" : endpoint.path - } -} diff --git a/instrumentation/reactor-3.1/reactor-3.1.gradle b/instrumentation/reactor-3.1/reactor-3.1.gradle deleted file mode 100644 index 1e816f298b..0000000000 --- a/instrumentation/reactor-3.1/reactor-3.1.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.projectreactor" - module = "reactor-core" - versions = "[3.1.0.RELEASE,)" - assertInverse = true - } -} - -dependencies { - implementation project(':instrumentation-core:reactor-3.1') - - testLibrary group: 'io.projectreactor', name: 'reactor-core', version: '3.1.0.RELEASE' - - latestDepTestLibrary group: 'io.projectreactor', name: 'reactor-core', version: '3.+' - // Looks like later versions on reactor need this dependency for some reason even though it is marked as optional. - latestDepTestLibrary group: 'io.micrometer', name: 'micrometer-core', version: '1.+' -} diff --git a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorHooksAdvice.java b/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorHooksAdvice.java deleted file mode 100644 index 9caa5e8e66..0000000000 --- a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorHooksAdvice.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.reactor; - -import io.opentelemetry.instrumentation.reactor.TracingOperator; -import net.bytebuddy.asm.Advice; - -public class ReactorHooksAdvice { - @Advice.OnMethodExit(suppress = Throwable.class) - public static void postStaticInitializer() { - TracingOperator.registerOnEachOperator(); - } -} diff --git a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorInstrumentationModule.java b/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorInstrumentationModule.java deleted file mode 100644 index f7f3eaaf07..0000000000 --- a/instrumentation/reactor-3.1/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/ReactorInstrumentationModule.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.reactor; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class ReactorInstrumentationModule extends InstrumentationModule { - - public ReactorInstrumentationModule() { - super("reactor", "reactor-3.1"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HooksInstrumentation()); - } - - public static class HooksInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("reactor.core.publisher.Hooks"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isTypeInitializer().or(named("resetOnEachOperator")), ReactorHooksAdvice.class.getName()); - } - } -} diff --git a/instrumentation/reactor-3.1/src/test/groovy/ReactorCoreTest.groovy b/instrumentation/reactor-3.1/src/test/groovy/ReactorCoreTest.groovy deleted file mode 100644 index 9ab7f1a396..0000000000 --- a/instrumentation/reactor-3.1/src/test/groovy/ReactorCoreTest.groovy +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan - -import io.opentelemetry.api.OpenTelemetry -import io.opentelemetry.context.Context -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.TraceUtils -import java.time.Duration -import org.reactivestreams.Publisher -import org.reactivestreams.Subscriber -import org.reactivestreams.Subscription -import reactor.core.publisher.Flux -import reactor.core.publisher.Mono -import spock.lang.Shared - -class ReactorCoreTest extends AgentTestRunner { - - public static final String EXCEPTION_MESSAGE = "test exception" - - @Shared - def addOne = { i -> - addOneFunc(i) - } - - @Shared - def addTwo = { i -> - addTwoFunc(i) - } - - @Shared - def throwException = { - throw new RuntimeException(EXCEPTION_MESSAGE) - } - - def "Publisher '#name' test"() { - when: - def result = runUnderTrace(publisherSupplier) - - then: - result == expected - and: - assertTraces(1) { - trace(0, workSpans + 2) { - span(0) { - name "trace-parent" - hasNoParent() - attributes { - } - } - span(1) { - name "publisher-parent" - childOf span(0) - attributes { - } - } - - basicSpan(it, 1, "publisher-parent", span(0)) - - for (int i = 0; i < workSpans; i++) { - span(i + 2) { - name "add one" - childOf span(1) - attributes { - } - } - } - } - } - - where: - paramName | expected | workSpans | publisherSupplier - "basic mono" | 2 | 1 | { -> Mono.just(1).map(addOne) } - "two operations mono" | 4 | 2 | { -> Mono.just(2).map(addOne).map(addOne) } - "delayed mono" | 4 | 1 | { -> - Mono.just(3).delayElement(Duration.ofMillis(100)).map(addOne) - } - "delayed twice mono" | 6 | 2 | { -> - Mono.just(4).delayElement(Duration.ofMillis(100)).map(addOne).delayElement(Duration.ofMillis(100)).map(addOne) - } - "basic flux" | [6, 7] | 2 | { -> Flux.fromIterable([5, 6]).map(addOne) } - "two operations flux" | [8, 9] | 4 | { -> - Flux.fromIterable([6, 7]).map(addOne).map(addOne) - } - "delayed flux" | [8, 9] | 2 | { -> - Flux.fromIterable([7, 8]).delayElements(Duration.ofMillis(100)).map(addOne) - } - "delayed twice flux" | [10, 11] | 4 | { -> - Flux.fromIterable([8, 9]).delayElements(Duration.ofMillis(100)).map(addOne).delayElements(Duration.ofMillis(100)).map(addOne) - } - - "mono from callable" | 12 | 2 | { -> - Mono.fromCallable({ addOneFunc(10) }).map(addOne) - } - } - - def "Publisher error '#name' test"() { - when: - runUnderTrace(publisherSupplier) - - then: - def exception = thrown RuntimeException - exception.message == EXCEPTION_MESSAGE - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "trace-parent" - errored true - errorEvent(RuntimeException, EXCEPTION_MESSAGE) - hasNoParent() - } - - // It's important that we don't attach errors at the Reactor level so that we don't - // impact the spans on reactor instrumentations such as netty and lettuce, as reactor is - // more of a context propagation mechanism than something we would be tracking for - // errors this is ok. - basicSpan(it, 1, "publisher-parent", span(0)) - } - } - - where: - paramName | publisherSupplier - "mono" | { -> Mono.error(new RuntimeException(EXCEPTION_MESSAGE)) } - "flux" | { -> Flux.error(new RuntimeException(EXCEPTION_MESSAGE)) } - } - - def "Publisher step '#name' test"() { - when: - runUnderTrace(publisherSupplier) - - then: - def exception = thrown RuntimeException - exception.message == EXCEPTION_MESSAGE - and: - assertTraces(1) { - trace(0, workSpans + 2) { - span(0) { - name "trace-parent" - errored true - errorEvent(RuntimeException, EXCEPTION_MESSAGE) - hasNoParent() - } - - // It's important that we don't attach errors at the Reactor level so that we don't - // impact the spans on reactor instrumentations such as netty and lettuce, as reactor is - // more of a context propagation mechanism than something we would be tracking for - // errors this is ok. - basicSpan(it, 1, "publisher-parent", span(0)) - - for (int i = 0; i < workSpans; i++) { - span(i + 2) { - name "add one" - childOf span(1) - attributes { - } - } - } - } - } - - where: - paramName | workSpans | publisherSupplier - "basic mono failure" | 1 | { -> Mono.just(1).map(addOne).map({ throwException() }) } - "basic flux failure" | 1 | { -> - Flux.fromIterable([5, 6]).map(addOne).map({ throwException() }) - } - } - - def "Publisher '#name' cancel"() { - when: - cancelUnderTrace(publisherSupplier) - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "trace-parent" - hasNoParent() - attributes { - } - } - - basicSpan(it, 1, "publisher-parent", span(0)) - } - } - - where: - paramName | publisherSupplier - "basic mono" | { -> Mono.just(1) } - "basic flux" | { -> Flux.fromIterable([5, 6]) } - } - - def "Publisher chain spans have the correct parent for '#name'"() { - when: - runUnderTrace(publisherSupplier) - - then: - assertTraces(1) { - trace(0, workSpans + 2) { - span(0) { - name "trace-parent" - hasNoParent() - attributes { - } - } - - basicSpan(it, 1, "publisher-parent", span(0)) - - for (int i = 0; i < workSpans; i++) { - span(i + 2) { - name "add one" - childOf span(1) - attributes { - } - } - } - } - } - - where: - paramName | workSpans | publisherSupplier - "basic mono" | 3 | { -> - Mono.just(1).map(addOne).map(addOne).then(Mono.just(1).map(addOne)) - } - "basic flux" | 5 | { -> - Flux.fromIterable([5, 6]).map(addOne).map(addOne).then(Mono.just(1).map(addOne)) - } - } - - def "Publisher chain spans have the correct parents from subscription time"() { - when: - def mono = Mono.just(42) - .map(addOne) - .map(addTwo) - TraceUtils.runUnderTrace("trace-parent") { - mono.block() - } - - then: - assertTraces(1) { - trace(0, 3) { - basicSpan(it, 0, "trace-parent") - basicSpan(it, 1, "add one", span(0)) - basicSpan(it, 2, "add two", span(0)) - } - } - - } - - def "Publisher chain spans have the correct parents from subscription time '#name'"() { - when: - runUnderTrace { - // The "add one" operations in the publisher created here should be children of the publisher-parent - Publisher publisher = publisherSupplier() - - def tracer = OpenTelemetry.getGlobalTracer("test") - def intermediate = tracer.spanBuilder("intermediate").startSpan() - // After this activation, the "add two" operations below should be children of this span - def scope = Context.current().with(intermediate).makeCurrent() - try { - if (publisher instanceof Mono) { - return ((Mono) publisher).map(addTwo) - } else if (publisher instanceof Flux) { - return ((Flux) publisher).map(addTwo) - } - throw new IllegalStateException("Unknown publisher type") - } finally { - intermediate.end() - scope.close() - } - } - - then: - assertTraces(1) { - trace(0, (workItems * 2) + 3) { - basicSpan(it, 0, "trace-parent") - basicSpan(it, 1, "publisher-parent", span(0)) - basicSpan(it, 2, "intermediate", span(1)) - - for (int i = 0; i < 2 * workItems; i = i + 2) { - basicSpan(it, 3 + i, "add one", span(1)) - basicSpan(it, 3 + i + 1, "add two", span(1)) - } - } - } - - where: - paramName | workItems | publisherSupplier - "basic mono" | 1 | { -> Mono.just(1).map(addOne) } - "basic flux" | 2 | { -> Flux.fromIterable([1, 2]).map(addOne) } - } - - def runUnderTrace(def publisherSupplier) { - TraceUtils.runUnderTrace("trace-parent") { - def tracer = OpenTelemetry.getGlobalTracer("test") - def span = tracer.spanBuilder("publisher-parent").startSpan() - def scope = Context.current().with(span).makeCurrent() - try { - def publisher = publisherSupplier() - // Read all data from publisher - if (publisher instanceof Mono) { - return publisher.block() - } else if (publisher instanceof Flux) { - return publisher.toStream().toArray({ size -> new Integer[size] }) - } - - throw new RuntimeException("Unknown publisher: " + publisher) - } finally { - span.end() - scope.close() - } - } - } - - def cancelUnderTrace(def publisherSupplier) { - TraceUtils.runUnderTrace("trace-parent") { - def tracer = OpenTelemetry.getGlobalTracer("test") - def span = tracer.spanBuilder("publisher-parent").startSpan() - def scope = Context.current().with(span).makeCurrent() - - def publisher = publisherSupplier() - publisher.subscribe(new Subscriber() { - void onSubscribe(Subscription subscription) { - subscription.cancel() - } - - void onNext(Integer t) { - } - - void onError(Throwable error) { - } - - void onComplete() { - } - }) - - span.end() - scope.close() - } - } - - static addOneFunc(int i) { - getTestTracer().spanBuilder("add one").startSpan().end() - return i + 1 - } - - static addTwoFunc(int i) { - getTestTracer().spanBuilder("add two").startSpan().end() - return i + 2 - } -} diff --git a/instrumentation/reactor-3.1/src/test/groovy/SubscriptionTest.groovy b/instrumentation/reactor-3.1/src/test/groovy/SubscriptionTest.groovy deleted file mode 100644 index 4fa62198a5..0000000000 --- a/instrumentation/reactor-3.1/src/test/groovy/SubscriptionTest.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.OpenTelemetry -import io.opentelemetry.instrumentation.test.AgentTestRunner -import java.util.concurrent.CountDownLatch -import reactor.core.publisher.Mono - -class SubscriptionTest extends AgentTestRunner { - - def "subscription test"() { - when: - CountDownLatch latch = new CountDownLatch(1) - runUnderTrace("parent") { - Mono connection = Mono.create { - it.success(new Connection()) - } - connection.subscribe { - it.query() - latch.countDown() - } - } - latch.await() - - then: - assertTraces(1) { - trace(0, 2) { - basicSpan(it, 0, "parent") - basicSpan(it, 1, "Connection.query", span(0)) - } - } - - } - - static class Connection { - static int query() { - def span = OpenTelemetry.getGlobalTracer("test").spanBuilder("Connection.query").startSpan() - span.end() - return new Random().nextInt() - } - } -} diff --git a/instrumentation/reactor-netty-0.9/reactor-netty-0.9.gradle b/instrumentation/reactor-netty-0.9/reactor-netty-0.9.gradle deleted file mode 100644 index 15cf7fe679..0000000000 --- a/instrumentation/reactor-netty-0.9/reactor-netty-0.9.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "io.projectreactor.netty" - module = "reactor-netty" - versions = "[0.9.0.RELEASE,1.0.0)" - } -} - -dependencies { - implementation project(':instrumentation:netty:netty-4.1') - library "io.projectreactor.netty:reactor-netty:0.9.0.RELEASE" - - latestDepTestLibrary group: 'io.projectreactor.netty', name: 'reactor-netty', version: '(,1.0.0)' -} diff --git a/instrumentation/reactor-netty-0.9/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/ReactorNettyInstrumentationModule.java b/instrumentation/reactor-netty-0.9/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/ReactorNettyInstrumentationModule.java deleted file mode 100644 index 1e7d7f6aa7..0000000000 --- a/instrumentation/reactor-netty-0.9/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/ReactorNettyInstrumentationModule.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.reactornetty; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.netty.bootstrap.Bootstrap; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import reactor.core.publisher.Mono; -import reactor.netty.Connection; -import reactor.netty.http.client.HttpClient; -import reactor.netty.http.client.HttpClientRequest; - -/** - * This instrumentation solves the problem of the correct context propagation through the roller - * coaster of Project Reactor and Netty thread hopping. It uses two public hooks of {@link - * HttpClient}: {@link HttpClient#mapConnect(BiFunction)} and {@link - * HttpClient#doOnRequest(BiConsumer)} two short-cut context propagation from the caller to Reactor - * to Netty. - */ -@AutoService(InstrumentationModule.class) -public class ReactorNettyInstrumentationModule extends InstrumentationModule { - - public ReactorNettyInstrumentationModule() { - super("reactor-netty", "reactor-netty-0.9"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new HttpClientInstrumentation()); - } - - public static class HttpClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("reactor.netty.http.client.HttpClient"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isStatic().and(named("create")), - ReactorNettyInstrumentationModule.class.getName() + "$CreateAdvice"); - } - } - - public static class CreateAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter() { - CallDepthThreadLocalMap.incrementCallDepth(HttpClient.class); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, @Advice.Return(readOnly = false) HttpClient client) { - - if (CallDepthThreadLocalMap.decrementCallDepth(HttpClient.class) == 0 && throwable == null) { - client = client.doOnRequest(new OnRequest()).mapConnect(new MapConnect()); - } - } - } - - public static class MapConnect - implements BiFunction, Bootstrap, Mono> { - - static final String CONTEXT_ATTRIBUTE = MapConnect.class.getName() + ".Context"; - - @Override - public Mono apply(Mono m, Bootstrap b) { - return m.subscriberContext(s -> s.put(CONTEXT_ATTRIBUTE, Context.current())); - } - } - - public static class OnRequest implements BiConsumer { - @Override - public void accept(HttpClientRequest r, Connection c) { - Context context = r.currentContext().get(MapConnect.CONTEXT_ATTRIBUTE); - c.channel().attr(AttributeKeys.CONNECT_CONTEXT).set(context); - } - } -} diff --git a/instrumentation/reactor-netty-0.9/src/test/groovy/HttpClientTest.groovy b/instrumentation/reactor-netty-0.9/src/test/groovy/HttpClientTest.groovy deleted file mode 100644 index aef04bb7e6..0000000000 --- a/instrumentation/reactor-netty-0.9/src/test/groovy/HttpClientTest.groovy +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.instrumentation.test.server.http.TestHttpServer.httpServer -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.sdk.trace.data.SpanData -import java.util.concurrent.CountDownLatch -import java.util.concurrent.Executors -import reactor.netty.http.client.HttpClient -import reactor.netty.http.client.HttpClientResponse -import spock.lang.AutoCleanup -import spock.lang.Shared - -class HttpClientTest extends AgentTestRunner { - @AutoCleanup - @Shared - def server = httpServer { - handlers { - prefix("success") { - response.status(200).send("Hello.") - } - } - } - - private int doRequest() { - HttpClientResponse resp = HttpClient.create() - .baseUrl(server.address.toString()) - .get() - .uri("/success") - .response() - .block() - return resp.status().code() - } - - def "concurrent requests"() { - def latch = new CountDownLatch(1) - def job = { - latch.await() - runUnderTrace("parent") { - doRequest() - } - } - - def pool = Executors.newFixedThreadPool(4) - - when: - 4.times { - pool.submit(job) - } - latch.countDown() - - then: - assertTraces(4) { - 4.times { - trace(it, 2) { - basicSpan(it, 0, "parent") - clientSpan(it, 1, span(0)) - } - } - } - - } - - void clientSpan(TraceAssert trace, int index, Object parentSpan, String method = "GET", URI uri = server.address.resolve("/success"), Integer status = 200) { - def userAgent = "ReactorNetty/" - trace.span(index) { - if (parentSpan == null) { - hasNoParent() - } else { - childOf((SpanData) parentSpan) - } - name "HTTP GET" - kind CLIENT - errored false - attributes { - "${SemanticAttributes.NET_TRANSPORT.key}" "IP.TCP" - "${SemanticAttributes.NET_PEER_NAME.key}" uri.host - "${SemanticAttributes.NET_PEER_IP.key}" { it == null || it == "127.0.0.1" } // Optional - "${SemanticAttributes.NET_PEER_PORT.key}" uri.port > 0 ? uri.port : { it == null || it == 443 } - "${SemanticAttributes.HTTP_URL.key}" uri.toString() - "${SemanticAttributes.HTTP_METHOD.key}" method - "${SemanticAttributes.HTTP_USER_AGENT.key}" { it.startsWith(userAgent) } - "${SemanticAttributes.HTTP_FLAVOR.key}" "1.1" - "${SemanticAttributes.HTTP_STATUS_CODE.key}" status - } - } - } - -} diff --git a/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy b/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy index 351b57e2cd..f4aed9e314 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy +++ b/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy @@ -6,9 +6,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import akka.actor.ActorSystem +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import redis.ByteStringDeserializerDefault import redis.ByteStringSerializerLowPriority import redis.RedisClient diff --git a/instrumentation/rediscala-1.8/rediscala-1.8.gradle b/instrumentation/rediscala-1.8/rediscala-1.8.gradle deleted file mode 100644 index fb45e082eb..0000000000 --- a/instrumentation/rediscala-1.8/rediscala-1.8.gradle +++ /dev/null @@ -1,51 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "com.github.etaty" - module = "rediscala_2.11" - versions = "[1.5.0,)" - assertInverse = true - } - - pass { - group = "com.github.etaty" - module = "rediscala_2.12" - versions = "[1.8.0,)" - assertInverse = true - } - - pass { - group = "com.github.etaty" - module = "rediscala_2.13" - versions = "[1.9.0,)" - assertInverse = true - } - - pass { - group = "com.github.Ma27" - module = "rediscala_2.11" - versions = "[1.8.1,)" - assertInverse = true - } - - pass { - group = "com.github.Ma27" - module = "rediscala_2.12" - versions = "[1.8.1,)" - assertInverse = true - } - - pass { - group = "com.github.Ma27" - module = "rediscala_2.13" - versions = "[1.9.0,)" - assertInverse = true - } -} - -dependencies { - library group: 'com.github.etaty', name: 'rediscala_2.11', version: '1.8.0' - - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' -} diff --git a/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java b/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java deleted file mode 100644 index e75a08f56f..0000000000 --- a/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaClientTracer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rediscala; - -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import java.net.InetSocketAddress; -import redis.RedisCommand; - -public class RediscalaClientTracer - extends DatabaseClientTracer, RedisCommand> { - - private static final RediscalaClientTracer TRACER = new RediscalaClientTracer(); - - public static RediscalaClientTracer tracer() { - return TRACER; - } - - @Override - protected String normalizeQuery(RedisCommand redisCommand) { - return spanNameForClass(redisCommand.getClass()); - } - - @Override - protected String dbSystem(RedisCommand redisCommand) { - return DbSystem.REDIS; - } - - @Override - protected InetSocketAddress peerAddress(RedisCommand redisCommand) { - return null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.rediscala"; - } -} diff --git a/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentationModule.java b/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentationModule.java deleted file mode 100644 index 92d3aa7d52..0000000000 --- a/instrumentation/rediscala-1.8/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaInstrumentationModule.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rediscala; - -import static io.opentelemetry.javaagent.instrumentation.rediscala.RediscalaClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import redis.RedisCommand; -import scala.concurrent.ExecutionContext; -import scala.concurrent.Future; -import scala.runtime.AbstractFunction1; -import scala.util.Try; - -@AutoService(InstrumentationModule.class) -public class RediscalaInstrumentationModule extends InstrumentationModule { - - public RediscalaInstrumentationModule() { - super("rediscala", "rediscala-1.8"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new RequestInstrumentation()); - } - - public static class RequestInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher classLoaderOptimization() { - return hasClassesNamed("redis.Request"); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - namedOneOf( - "redis.ActorRequest", - "redis.Request", - "redis.BufferedRequest", - "redis.RoundRobinPoolRequest")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isPublic()) - .and(named("send")) - .and(takesArgument(0, named("redis.RedisCommand"))) - .and(returns(named("scala.concurrent.Future"))), - RediscalaInstrumentationModule.class.getName() + "$RediscalaAdvice"); - } - } - - public static class RediscalaAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) RedisCommand cmd, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(cmd, cmd); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope, - @Advice.Thrown Throwable throwable, - @Advice.FieldValue("executionContext") ExecutionContext ctx, - @Advice.Return(readOnly = false) Future responseFuture) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - responseFuture.onComplete(new OnCompleteHandler(span), ctx); - } - } - } - - public static class OnCompleteHandler extends AbstractFunction1, Void> { - private final Span span; - - public OnCompleteHandler(Span span) { - this.span = span; - } - - @Override - public Void apply(Try result) { - if (result.isFailure()) { - tracer().endExceptionally(span, result.failed().get()); - } else { - tracer().end(span); - } - return null; - } - } -} diff --git a/instrumentation/rediscala-1.8/src/test/groovy/RediscalaClientTest.groovy b/instrumentation/rediscala-1.8/src/test/groovy/RediscalaClientTest.groovy deleted file mode 100644 index f4aed9e314..0000000000 --- a/instrumentation/rediscala-1.8/src/test/groovy/RediscalaClientTest.groovy +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import akka.actor.ActorSystem -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import redis.ByteStringDeserializerDefault -import redis.ByteStringSerializerLowPriority -import redis.RedisClient -import redis.RedisDispatcher -import redis.embedded.RedisServer -import scala.Option -import scala.concurrent.Await -import scala.concurrent.duration.Duration -import spock.lang.Shared - -class RediscalaClientTest extends AgentTestRunner { - - @Shared - int port = PortUtils.randomOpenPort() - - @Shared - RedisServer redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind 127.0.0.1") - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - - @Shared - ActorSystem system - - @Shared - RedisClient redisClient - - def setupSpec() { - system = ActorSystem.create() - redisClient = new RedisClient("localhost", - port, - Option.apply(null), - Option.apply(null), - "RedisClient", - Option.apply(null), - system, - new RedisDispatcher("rediscala.rediscala-client-worker-dispatcher")) - - println "Using redis: $redisServer.args" - redisServer.start() - } - - def cleanupSpec() { - redisServer.stop() - system?.terminate() - } - - def "set command"() { - when: - def value = redisClient.set("foo", - "bar", - Option.apply(null), - Option.apply(null), - false, - false, - new ByteStringSerializerLowPriority.String$()) - - - then: - Await.result(value, Duration.apply("3 second")) == true - assertTraces(1) { - trace(0, 1) { - span(0) { - name "Set" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "Set" - } - } - } - } - } - - def "get command"() { - when: - def write = redisClient.set("bar", - "baz", - Option.apply(null), - Option.apply(null), - false, - false, - new ByteStringSerializerLowPriority.String$()) - def value = redisClient.get("bar", new ByteStringDeserializerDefault.String$()) - - then: - Await.result(write, Duration.apply("3 second")) == true - Await.result(value, Duration.apply("3 second")) == Option.apply("baz") - assertTraces(2) { - trace(0, 1) { - span(0) { - name "Set" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "Set" - } - } - } - trace(1, 1) { - span(0) { - name "Get" - kind CLIENT - attributes { - "${SemanticAttributes.DB_SYSTEM.key()}" "redis" - "${SemanticAttributes.DB_STATEMENT.key()}" "Get" - } - } - } - } - } -} diff --git a/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonAsyncClientTest.groovy b/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonAsyncClientTest.groovy index 290328ca57..7950229bd4 100644 --- a/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonAsyncClientTest.groovy +++ b/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonAsyncClientTest.groovy @@ -5,9 +5,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.util.concurrent.TimeUnit import org.redisson.Redisson import org.redisson.api.RBucket diff --git a/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonClientTest.groovy b/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonClientTest.groovy index ec00f558f2..8e2ddd2a9f 100644 --- a/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonClientTest.groovy +++ b/instrumentation/redisson-3.0/javaagent/src/test/groovy/RedissonClientTest.groovy @@ -7,9 +7,9 @@ import static io.opentelemetry.api.trace.Span.Kind.CLIENT import static java.util.regex.Pattern.compile import static java.util.regex.Pattern.quote +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import org.redisson.Redisson import org.redisson.api.RAtomicLong import org.redisson.api.RBatch diff --git a/instrumentation/redisson-3.0/redisson-3.0.gradle b/instrumentation/redisson-3.0/redisson-3.0.gradle deleted file mode 100644 index f4486d40cb..0000000000 --- a/instrumentation/redisson-3.0/redisson-3.0.gradle +++ /dev/null @@ -1,18 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - group = "org.redisson" - module = "redisson" - versions = "[3.0.0,)" - } -} - -dependencies { - library group: 'org.redisson', name: 'redisson', version: '3.0.0' - testImplementation group: 'com.github.kstyrc', name: 'embedded-redis', version: '0.6' -} - -test { - systemProperty "testLatestDeps", testLatestDeps -} diff --git a/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java b/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java deleted file mode 100644 index 999d898e30..0000000000 --- a/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonClientTracer.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.redisson; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.Channel; -import io.opentelemetry.instrumentation.api.tracer.DatabaseClientTracer; -import io.opentelemetry.javaagent.instrumentation.api.db.DbSystem; -import io.opentelemetry.javaagent.instrumentation.api.db.RedisCommandNormalizer; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import org.redisson.client.RedisConnection; -import org.redisson.client.protocol.CommandData; -import org.redisson.client.protocol.CommandsData; - -public class RedissonClientTracer extends DatabaseClientTracer { - private static final String UNKNOWN_COMMAND = "Redis Command"; - - private static final RedissonClientTracer TRACER = new RedissonClientTracer(); - - public static RedissonClientTracer tracer() { - return TRACER; - } - - private final RedisCommandNormalizer commandNormalizer = - new RedisCommandNormalizer("redisson", "redisson-3.0"); - - @Override - protected String spanName(RedisConnection connection, Object query, String normalizedQuery) { - if (query instanceof CommandsData) { - List> commands = ((CommandsData) query).getCommands(); - StringBuilder commandStrings = new StringBuilder(); - for (CommandData commandData : commands) { - commandStrings.append(commandData.getCommand().getName()).append(";"); - } - if (commandStrings.length() > 0) { - commandStrings.deleteCharAt(commandStrings.length() - 1); - } - return commandStrings.toString(); - } else if (query instanceof CommandData) { - return ((CommandData) query).getCommand().getName(); - } - - return UNKNOWN_COMMAND; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.redisson"; - } - - @Override - protected String normalizeQuery(Object command) { - // get command - if (command instanceof CommandsData) { - List> commands = ((CommandsData) command).getCommands(); - StringBuilder commandStrings = new StringBuilder(); - for (CommandData commandData : commands) { - commandStrings.append(normalizeSingleCommand(commandData)).append(";"); - } - if (commandStrings.length() > 0) { - commandStrings.deleteCharAt(commandStrings.length() - 1); - } - return commandStrings.toString(); - } else if (command instanceof CommandData) { - return normalizeSingleCommand((CommandData) command); - } - return UNKNOWN_COMMAND; - } - - private String normalizeSingleCommand(CommandData command) { - Object[] commandParams = command.getParams(); - List args = new ArrayList<>(commandParams.length + 1); - if (command.getCommand().getSubName() != null) { - args.add(command.getCommand().getSubName()); - } - for (Object param : commandParams) { - if (param instanceof ByteBuf) { - try { - // slice() does not copy the actual byte buffer, it only returns a readable/writable - // "view" of the original buffer (i.e. read and write marks are not shared) - ByteBuf buf = ((ByteBuf) param).slice(); - // state can be null here: no Decoders used by Codecs use it - args.add(command.getCodec().getValueDecoder().decode(buf, null)); - } catch (Exception ignored) { - args.add("?"); - } - } else { - args.add(param); - } - } - return commandNormalizer.normalize(command.getCommand().getName(), args); - } - - @Override - protected String dbSystem(RedisConnection connection) { - return DbSystem.REDIS; - } - - @Override - protected InetSocketAddress peerAddress(RedisConnection connection) { - Channel channel = connection.getChannel(); - return (InetSocketAddress) channel.remoteAddress(); - } - - @Override - protected String dbConnectionString(RedisConnection connection) { - Channel channel = connection.getChannel(); - InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress(); - return remoteAddress.getHostString() + ":" + remoteAddress.getPort(); - } -} diff --git a/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java b/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java deleted file mode 100644 index f9cce747dd..0000000000 --- a/instrumentation/redisson-3.0/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonInstrumentation.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.redisson; - -import static io.opentelemetry.javaagent.instrumentation.redisson.RedissonClientTracer.tracer; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.redisson.client.RedisConnection; - -@AutoService(InstrumentationModule.class) -public class RedissonInstrumentation extends InstrumentationModule { - - public RedissonInstrumentation() { - super("redisson", "redisson-3.0"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new RedisConnectionInstrumentation()); - } - - public static class RedisConnectionInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return named("org.redisson.client.RedisConnection"); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(named("send")), - RedissonInstrumentation.class.getName() + "$RedissonAdvice"); - } - } - - public static class RedissonAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This RedisConnection connection, - @Advice.Argument(0) Object arg, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - span = tracer().startSpan(connection, arg); - scope = tracer().startScope(span); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/redisson-3.0/src/test/groovy/RedissonAsyncClientTest.groovy b/instrumentation/redisson-3.0/src/test/groovy/RedissonAsyncClientTest.groovy deleted file mode 100644 index 7950229bd4..0000000000 --- a/instrumentation/redisson-3.0/src/test/groovy/RedissonAsyncClientTest.groovy +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.util.concurrent.TimeUnit -import org.redisson.Redisson -import org.redisson.api.RBucket -import org.redisson.api.RFuture -import org.redisson.api.RList -import org.redisson.api.RSet -import org.redisson.api.RedissonClient -import org.redisson.config.Config -import redis.embedded.RedisServer -import spock.lang.Shared - -class RedissonAsyncClientTest extends AgentTestRunner { - - @Shared - int port = PortUtils.randomOpenPort() - - @Shared - RedisServer redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind 127.0.0.1") - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - @Shared - RedissonClient redisson - @Shared - String address = "localhost:" + port - - def setupSpec() { - if (Boolean.getBoolean("testLatestDeps")) { - // Newer versions of redisson require scheme, older versions forbid it - address = "redis://" + address - } - println "Using redis: $redisServer.args" - redisServer.start() - } - - def cleanupSpec() { - redisson.shutdown() - redisServer.stop() - } - - def setup() { - Config config = new Config() - config.useSingleServer().setAddress(address) - redisson = Redisson.create(config) - TEST_WRITER.clear() - } - - def "test future set"() { - when: - RBucket keyObject = redisson.getBucket("foo") - RFuture future = keyObject.setAsync("bar") - future.get(3, TimeUnit.SECONDS) - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - } - } - } - } - } - - def "test future whenComplete"() { - when: - RSet rSet = redisson.getSet("set1") - RFuture result = rSet.addAsync("s1") - result.whenComplete({ res, throwable -> - RList strings = redisson.getList("list1") - strings.add("a") - }) - - then: - result.get(3, TimeUnit.SECONDS) - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SADD" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "SADD set1 ?" - } - } - } - trace(1, 1) { - span(0) { - name "RPUSH" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "RPUSH list1 ?" - } - } - } - } - } - -} - diff --git a/instrumentation/redisson-3.0/src/test/groovy/RedissonClientTest.groovy b/instrumentation/redisson-3.0/src/test/groovy/RedissonClientTest.groovy deleted file mode 100644 index 8e2ddd2a9f..0000000000 --- a/instrumentation/redisson-3.0/src/test/groovy/RedissonClientTest.groovy +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static java.util.regex.Pattern.compile -import static java.util.regex.Pattern.quote - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import org.redisson.Redisson -import org.redisson.api.RAtomicLong -import org.redisson.api.RBatch -import org.redisson.api.RBucket -import org.redisson.api.RList -import org.redisson.api.RLock -import org.redisson.api.RMap -import org.redisson.api.RScoredSortedSet -import org.redisson.api.RSet -import org.redisson.api.RedissonClient -import org.redisson.config.Config -import redis.embedded.RedisServer -import spock.lang.Shared - -class RedissonClientTest extends AgentTestRunner { - - @Shared - int port = PortUtils.randomOpenPort() - - @Shared - RedisServer redisServer = RedisServer.builder() - // bind to localhost to avoid firewall popup - .setting("bind 127.0.0.1") - // set max memory to avoid problems in CI - .setting("maxmemory 128M") - .port(port).build() - @Shared - RedissonClient redisson - @Shared - String address = "localhost:" + port - - def setupSpec() { - if (Boolean.getBoolean("testLatestDeps")) { - // Newer versions of redisson require scheme, older versions forbid it - address = "redis://" + address - } - println "Using redis: $redisServer.args" - redisServer.start() - } - - def cleanupSpec() { - redisson.shutdown() - redisServer.stop() - } - - def setup() { - Config config = new Config() - config.useSingleServer().setAddress(address) - redisson = Redisson.create(config) - TEST_WRITER.clear() - } - - def "test string command"() { - when: - RBucket keyObject = redisson.getBucket("foo") - keyObject.set("bar") - keyObject.get() - - then: - assertTraces(2) { - trace(0, 1) { - span(0) { - name "SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "SET foo ?" - } - } - } - trace(1, 1) { - span(0) { - name "GET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "GET foo" - } - } - } - } - } - - def "test batch command"() { - when: - RBatch batch = redisson.createBatch() - batch.getBucket("batch1").setAsync("v1") - batch.getBucket("batch2").setAsync("v2") - batch.execute() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SET;SET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "SET batch1 ?;SET batch2 ?" - } - } - } - } - } - - def "test list command"() { - when: - RList strings = redisson.getList("list1") - strings.add("a") - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "RPUSH" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "RPUSH list1 ?" - } - } - } - } - } - - def "test hash command"() { - when: - RMap rMap = redisson.getMap("map1") - rMap.put("key1", "value1") - rMap.get("key1") - - then: - assertTraces(2) { - trace(0, 1) { - span(0) { - def script = "local v = redis.call('hget', KEYS[1], ARGV[1]); redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); return v" - - name "EVAL" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "EVAL $script 1 map1 ? ?" - } - } - } - trace(1, 1) { - span(0) { - name "HGET" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "HGET map1 key1" - } - } - } - } - } - - def "test set command"() { - when: - RSet rSet = redisson.getSet("set1") - rSet.add("s1") - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "SADD" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "SADD set1 ?" - } - } - } - } - } - - def "test sorted set command"() { - when: - Map scores = new HashMap<>() - scores.put("u1", 1.0d) - scores.put("u2", 3.0d) - scores.put("u3", 0.0d) - RScoredSortedSet sortSet = redisson.getScoredSortedSet("sort_set1") - sortSet.addAll(scores) - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "ZADD" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "ZADD sort_set1 ? ? ? ? ? ?" - } - } - } - } - } - - def "test AtomicLong command"() { - when: - RAtomicLong atomicLong = redisson.getAtomicLong("AtomicLong") - atomicLong.incrementAndGet() - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "INCR" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" "INCR AtomicLong" - } - } - } - } - } - - def "test lock command"() { - when: - RLock lock = redisson.getLock("lock") - lock.lock() - lock.unlock() - - then: - assertTraces(2) { - trace(0, 1) { - span(0) { - // Use .* to match the actual script, since it changes between redisson versions - // everything that does not change is quoted so that it's matched literally - def lockScriptPattern = compile("^" + quote("EVAL ") + ".*" + quote(" 1 lock ? ?") + "\$") - - name "EVAL" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" { lockScriptPattern.matcher(it).matches() } - } - } - } - trace(1, 1) { - span(0) { - def lockScriptPattern = compile("^" + quote("EVAL ") + ".*" + quote(" 2 lock ") + "\\S+" + quote(" ? ? ?") + "\$") - - name "EVAL" - kind CLIENT - attributes { - "$SemanticAttributes.DB_SYSTEM.key" "redis" - "$SemanticAttributes.NET_PEER_IP.key" "127.0.0.1" - "$SemanticAttributes.NET_PEER_NAME.key" "localhost" - "$SemanticAttributes.DB_CONNECTION_STRING.key" "localhost:$port" - "$SemanticAttributes.NET_PEER_PORT.key" port - "$SemanticAttributes.DB_STATEMENT.key" { lockScriptPattern.matcher(it).matches() } - } - } - } - } - } -} - diff --git a/instrumentation/rmi/javaagent/src/test/groovy/RmiTest.groovy b/instrumentation/rmi/javaagent/src/test/groovy/RmiTest.groovy index a5c8a9fb73..c011f04cc7 100644 --- a/instrumentation/rmi/javaagent/src/test/groovy/RmiTest.groovy +++ b/instrumentation/rmi/javaagent/src/test/groovy/RmiTest.groovy @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace import static io.opentelemetry.api.trace.Span.Kind.CLIENT import static io.opentelemetry.api.trace.Span.Kind.SERVER +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan +import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace +import io.opentelemetry.api.trace.attributes.SemanticAttributes import io.opentelemetry.instrumentation.test.AgentTestRunner import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.api.trace.attributes.SemanticAttributes import java.rmi.registry.LocateRegistry import java.rmi.server.UnicastRemoteObject import rmi.app.Greeter diff --git a/instrumentation/rmi/rmi.gradle b/instrumentation/rmi/rmi.gradle deleted file mode 100644 index b0f98217e8..0000000000 --- a/instrumentation/rmi/rmi.gradle +++ /dev/null @@ -1,31 +0,0 @@ -apply from: "$rootDir/gradle/instrumentation.gradle" - -muzzle { - pass { - coreJdk() - } -} - -task "rmic", dependsOn: testClasses { - def clazz = 'rmi.app.ServerLegacy' - String command = """rmic -g -keep -classpath ${sourceSets.test.output.classesDirs.asPath} -d ${buildDir}/classes/java/test ${clazz}""" - command.execute().text -} - -test.dependsOn "rmic" - -// We cannot use "--release" javac option here because that will forbid importing "sun.rmi" package. -// We also can't seem to use the toolchain without the "--release" option. So disable everything. - -java { - toolchain { - languageVersion = null - } -} - -tasks.withType(JavaCompile) { - options.release = null -} -tasks.withType(GroovyCompile) { - options.release = null -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentationModule.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentationModule.java deleted file mode 100644 index 7a277820b1..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientInstrumentationModule.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.client; - -import static io.opentelemetry.javaagent.instrumentation.rmi.client.RmiClientTracer.tracer; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class RmiClientInstrumentationModule extends InstrumentationModule { - - public RmiClientInstrumentationModule() { - super("rmi", "rmi-client"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ClientInstrumentation()); - } - - public static class ClientInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("sun.rmi.server.UnicastRef")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(named("invoke")) - .and(takesArgument(0, named("java.rmi.Remote"))) - .and(takesArgument(1, named("java.lang.reflect.Method"))), - RmiClientInstrumentationModule.class.getName() + "$RmiClientAdvice"); - } - } - - public static class RmiClientAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(value = 1) Method method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - - // TODO replace with client span check - if (!Java8BytecodeBridge.currentSpan().getSpanContext().isValid()) { - return; - } - span = tracer().startSpan(method); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - if (throwable != null) { - tracer().endExceptionally(span, throwable); - } else { - tracer().end(span); - } - } - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientTracer.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientTracer.java deleted file mode 100644 index df2a3bb55a..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/client/RmiClientTracer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.client; - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.instrumentation.api.tracer.RpcClientTracer; -import java.lang.reflect.Method; - -public class RmiClientTracer extends RpcClientTracer { - private static final RmiClientTracer TRACER = new RmiClientTracer(); - - public static RmiClientTracer tracer() { - return TRACER; - } - - @Override - public Span startSpan(Method method) { - String serviceName = method.getDeclaringClass().getName(); - String methodName = method.getName(); - - SpanBuilder spanBuilder = - tracer.spanBuilder(serviceName + "/" + methodName).setSpanKind(CLIENT); - spanBuilder.setAttribute(SemanticAttributes.RPC_SYSTEM, "java_rmi"); - spanBuilder.setAttribute(SemanticAttributes.RPC_SERVICE, serviceName); - spanBuilder.setAttribute(SemanticAttributes.RPC_METHOD, methodName); - - return spanBuilder.startSpan(); - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.rmi"; - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPayload.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPayload.java deleted file mode 100644 index ba7a4456cb..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPayload.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.context; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** ContextPayload wraps context information shared between client and server. */ -public class ContextPayload { - - private static final Logger log = LoggerFactory.getLogger(ContextPayload.class); - - private static final Tracer TRACER = OpenTelemetry.getGlobalTracer("io.opentelemetry.auto.rmi"); - - public static Tracer tracer() { - return TRACER; - } - - private final Map context; - public static final ExtractAdapter GETTER = new ExtractAdapter(); - public static final InjectAdapter SETTER = new InjectAdapter(); - - public ContextPayload() { - context = new HashMap<>(); - } - - public ContextPayload(Map context) { - this.context = context; - } - - public static ContextPayload from(Span span) { - ContextPayload payload = new ContextPayload(); - Context context = Context.current().with(span); - OpenTelemetry.getGlobalPropagators().getTextMapPropagator().inject(context, payload, SETTER); - return payload; - } - - public static ContextPayload read(ObjectInput oi) throws IOException { - try { - Object object = oi.readObject(); - if (object instanceof Map) { - return new ContextPayload((Map) object); - } - } catch (ClassCastException | ClassNotFoundException ex) { - log.debug("Error reading object", ex); - } - - return null; - } - - public Map getSpanContext() { - return context; - } - - public void write(ObjectOutput out) throws IOException { - out.writeObject(context); - } - - public static class ExtractAdapter implements TextMapPropagator.Getter { - @Override - public Iterable keys(ContextPayload contextPayload) { - return contextPayload.getSpanContext().keySet(); - } - - @Override - public String get(ContextPayload carrier, String key) { - return carrier.getSpanContext().get(key); - } - } - - public static class InjectAdapter implements TextMapPropagator.Setter { - @Override - public void set(ContextPayload carrier, String key, String value) { - carrier.getSpanContext().put(key, value); - } - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPropagator.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPropagator.java deleted file mode 100644 index 8adfcc29b3..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/ContextPropagator.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.context; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import java.io.IOException; -import java.io.ObjectOutput; -import java.rmi.NoSuchObjectException; -import java.rmi.server.ObjID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.rmi.transport.Connection; -import sun.rmi.transport.StreamRemoteCall; -import sun.rmi.transport.TransportConstants; - -public class ContextPropagator { - - private static final Logger log = LoggerFactory.getLogger(ContextPropagator.class); - - // Internal RMI object ids that we don't want to trace - private static final ObjID ACTIVATOR_ID = new ObjID(ObjID.ACTIVATOR_ID); - private static final ObjID DGC_ID = new ObjID(ObjID.DGC_ID); - private static final ObjID REGISTRY_ID = new ObjID(ObjID.REGISTRY_ID); - - // RMI object id used to identify agent instrumentation - public static final ObjID CONTEXT_CALL_ID = - new ObjID("io.opentelemetry.auto.v1.context_call".hashCode()); - - // Operation id used for checking context propagation is possible - // RMI expects these operations to have negative identifier, as positive ones mean legacy - // precompiled Stubs would be used instead - private static final int CONTEXT_CHECK_CALL_OPERATION_ID = -1; - // Seconds step of context propagation which contains actual payload - private static final int CONTEXT_PAYLOAD_OPERATION_ID = -2; - - public static final ContextPropagator PROPAGATOR = new ContextPropagator(); - - public boolean isRmiInternalObject(ObjID id) { - return ACTIVATOR_ID.equals(id) || DGC_ID.equals(id) || REGISTRY_ID.equals(id); - } - - public boolean isOperationWithPayload(int operationId) { - return operationId == CONTEXT_PAYLOAD_OPERATION_ID; - } - - public void attemptToPropagateContext( - ContextStore knownConnections, Connection c, Span span) { - if (checkIfContextCanBePassed(knownConnections, c)) { - if (!syntheticCall(c, ContextPayload.from(span), CONTEXT_PAYLOAD_OPERATION_ID)) { - log.debug("Couldn't send context payload"); - } - } - } - - private boolean checkIfContextCanBePassed( - ContextStore knownConnections, Connection c) { - Boolean storedResult = knownConnections.get(c); - if (storedResult != null) { - return storedResult; - } - - boolean result = syntheticCall(c, null, CONTEXT_CHECK_CALL_OPERATION_ID); - knownConnections.put(c, result); - return result; - } - - /** Returns true when no error happened during call. */ - private boolean syntheticCall(Connection c, ContextPayload payload, int operationId) { - StreamRemoteCall shareContextCall = new StreamRemoteCall(c); - try { - c.getOutputStream().write(TransportConstants.Call); - - ObjectOutput out = shareContextCall.getOutputStream(); - - CONTEXT_CALL_ID.write(out); - - // call header, part 2 (read by Dispatcher) - out.writeInt(operationId); // in normal call this is method number (operation index) - out.writeLong(operationId); // in normal RMI call this holds stub/skeleton hash - - // Payload should be sent only after we make sure we're connected to instrumented server - // - // if method is not found by un-instrumented code then writing payload will cause an exception - // in RMI server - as the payload will be interpreted as another call - // but it will not be parsed correctly - closing connection - if (payload != null) { - payload.write(out); - } - - try { - shareContextCall.executeCall(); - } catch (Exception e) { - Exception ex = shareContextCall.getServerException(); - if (ex != null) { - if (ex instanceof NoSuchObjectException) { - return false; - } else { - log.debug("Server error when executing synthetic call", ex); - } - } else { - log.debug("Error executing synthetic call", e); - } - return false; - } finally { - shareContextCall.done(); - } - - } catch (IOException e) { - log.debug("Communication error executing synthetic call", e); - return false; - } - return true; - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java deleted file mode 100644 index 2130065bde..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.context; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.rmi.context.client.RmiClientContextInstrumentation; -import io.opentelemetry.javaagent.instrumentation.rmi.context.server.RmiServerContextInstrumentation; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.List; -import java.util.Map; - -@AutoService(InstrumentationModule.class) -public class RmiContextPropagationInstrumentationModule extends InstrumentationModule { - public RmiContextPropagationInstrumentationModule() { - super("rmi", "rmi-context-propagation"); - } - - @Override - public List typeInstrumentations() { - return asList(new RmiClientContextInstrumentation(), new RmiServerContextInstrumentation()); - } - - @Override - public Map contextStore() { - // caching if a connection can support enhanced format - return singletonMap("sun.rmi.transport.Connection", "java.lang.Boolean"); - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java deleted file mode 100644 index 00b43f1f22..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.context.client; - -import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator.PROPAGATOR; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isConstructor; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.javaagent.instrumentation.api.ContextStore; -import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; -import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.rmi.server.ObjID; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import sun.rmi.transport.Connection; - -/** - * Main entry point for transferring context between RMI service. - * - *

It injects into StreamRemoteCall constructor used for invoking remote tasks and performs a - * backwards compatible check to ensure if the other side is prepared to receive context propagation - * messages then if successful sends a context propagation message - * - *

Context propagation consist of a Serialized HashMap with all data set by usual context - * injection, which includes things like sampling priority, trace and parent id - * - *

As well as optional baggage items - * - *

On the other side of the communication a special Dispatcher is created when a message with - * CONTEXT_CALL_ID is received. - * - *

If the server is not instrumented first call will gracefully fail just like any other unknown - * call. With small caveat that this first call needs to *not* have any parameters, since those will - * not be read from connection and instead will be interpreted as another remote instruction, but - * that instruction will essentially be garbage data and will cause the parsing loop to throw - * exception and shutdown the connection which we do not want - */ -public class RmiClientContextInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("sun.rmi.transport.StreamRemoteCall")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isConstructor() - .and(takesArgument(0, named("sun.rmi.transport.Connection"))) - .and(takesArgument(1, named("java.rmi.server.ObjID"))), - getClass().getName() + "$StreamRemoteCallConstructorAdvice"); - } - - public static class StreamRemoteCallConstructorAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter(@Advice.Argument(0) Connection c, @Advice.Argument(1) ObjID id) { - if (!c.isReusable()) { - return; - } - if (PROPAGATOR.isRmiInternalObject(id)) { - return; - } - Span activeSpan = Java8BytecodeBridge.currentSpan(); - if (!activeSpan.getSpanContext().isValid()) { - return; - } - - ContextStore knownConnections = - InstrumentationContext.get(Connection.class, Boolean.class); - - PROPAGATOR.attemptToPropagateContext(knownConnections, c, activeSpan); - } - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/ContextDispatcher.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/ContextDispatcher.java deleted file mode 100644 index 12bbf54a5d..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/ContextDispatcher.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.context.server; - -import static io.opentelemetry.instrumentation.api.tracer.BaseTracer.extract; -import static io.opentelemetry.javaagent.instrumentation.api.rmi.ThreadLocalContext.THREAD_LOCAL_CONTEXT; -import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload.GETTER; -import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator.CONTEXT_CALL_ID; -import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator.PROPAGATOR; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPayload; -import java.io.IOException; -import java.io.ObjectInput; -import java.rmi.Remote; -import java.rmi.server.RemoteCall; -import sun.rmi.server.Dispatcher; -import sun.rmi.transport.Target; - -/** - * ContextDispatcher is responsible for handling both initial context propagation check call and - * following call which carries payload - * - *

Context propagation check is only expected not to throw any exception, hinting to the client - * that its communicating with an instrumented server. Non instrumented server would've thrown - * UnknownObjectException - * - *

Because caching of the result after first call on a connection, only payload calls are - * expected - */ -public class ContextDispatcher implements Dispatcher { - private static final ContextDispatcher CONTEXT_DISPATCHER = new ContextDispatcher(); - private static final NoopRemote NOOP_REMOTE = new NoopRemote(); - - public static Target newDispatcherTarget() { - return new Target(NOOP_REMOTE, CONTEXT_DISPATCHER, NOOP_REMOTE, CONTEXT_CALL_ID, false); - } - - @Override - public void dispatch(Remote obj, RemoteCall call) throws IOException { - ObjectInput in = call.getInputStream(); - int operationId = in.readInt(); - in.readLong(); // skip 8 bytes - - if (PROPAGATOR.isOperationWithPayload(operationId)) { - ContextPayload payload = ContextPayload.read(in); - if (payload != null) { - Context context = extract(payload, GETTER); - SpanContext spanContext = Span.fromContext(context).getSpanContext(); - if (spanContext.isValid()) { - THREAD_LOCAL_CONTEXT.set(context); - } else { - THREAD_LOCAL_CONTEXT.set(null); - } - } - } - - // send result stream the client is expecting - call.getResultStream(true); - - // release held streams to allow next call to continue - call.releaseInputStream(); - call.releaseOutputStream(); - call.done(); - } - - public static class NoopRemote implements Remote {} -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java deleted file mode 100644 index d513a1a14a..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/server/RmiServerContextInstrumentation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.context.server; - -import static io.opentelemetry.javaagent.instrumentation.rmi.context.ContextPropagator.CONTEXT_CALL_ID; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonMap; -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.tooling.TypeInstrumentation; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; -import sun.rmi.transport.Target; - -public class RmiServerContextInstrumentation implements TypeInstrumentation { - - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("sun.rmi.transport.ObjectTable")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod() - .and(isStatic()) - .and(named("getTarget")) - .and((takesArgument(0, named("sun.rmi.transport.ObjectEndpoint")))), - getClass().getName() + "$ObjectTableAdvice"); - } - - public static class ObjectTableAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void methodExit( - @Advice.Argument(0) Object oe, @Advice.Return(readOnly = false) Target result) { - // comparing toString() output allows us to avoid using reflection to be able to compare - // ObjID and ObjectEndpoint objects - // ObjectEndpoint#toString() only returns this.objId.toString() value which is exactly - // what we're interested in here. - if (!CONTEXT_CALL_ID.toString().equals(oe.toString())) { - return; - } - result = ContextDispatcher.newDispatcherTarget(); - } - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java deleted file mode 100644 index fdea548c32..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerInstrumentation.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.server; - -import static io.opentelemetry.javaagent.instrumentation.api.rmi.ThreadLocalContext.THREAD_LOCAL_CONTEXT; -import static io.opentelemetry.javaagent.instrumentation.rmi.server.RmiServerTracer.tracer; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.isStatic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.instrumentation.api.CallDepthThreadLocalMap; -import io.opentelemetry.javaagent.tooling.InstrumentationModule; -import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.lang.reflect.Method; -import java.rmi.server.RemoteServer; -import java.util.List; -import java.util.Map; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -@AutoService(InstrumentationModule.class) -public class RmiServerInstrumentation extends InstrumentationModule { - - public RmiServerInstrumentation() { - super("rmi", "rmi-server"); - } - - @Override - public List typeInstrumentations() { - return singletonList(new ServerInstrumentation()); - } - - public static class ServerInstrumentation implements TypeInstrumentation { - @Override - public ElementMatcher typeMatcher() { - return extendsClass(named("java.rmi.server.RemoteServer")); - } - - @Override - public Map, String> transformers() { - return singletonMap( - isMethod().and(isPublic()).and(not(isStatic())), - RmiServerInstrumentation.class.getName() + "$ServerAdvice"); - } - } - - public static class ServerAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Origin Method method, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - int callDepth = CallDepthThreadLocalMap.incrementCallDepth(RemoteServer.class); - if (callDepth > 0) { - return; - } - - // TODO review and unify with all other SERVER instrumentation - Context context = THREAD_LOCAL_CONTEXT.getAndResetContext(); - - span = tracer().startSpan(method, context); - scope = span.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void stopSpan( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelSpan") Span span, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } - scope.close(); - - CallDepthThreadLocalMap.reset(RemoteServer.class); - if (throwable != null) { - RmiServerTracer.tracer().endExceptionally(span, throwable); - } else { - RmiServerTracer.tracer().end(span); - } - } - } -} diff --git a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerTracer.java b/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerTracer.java deleted file mode 100644 index c116135810..0000000000 --- a/instrumentation/rmi/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/server/RmiServerTracer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.rmi.server; - -import static io.opentelemetry.api.trace.Span.Kind.SERVER; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.attributes.SemanticAttributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapPropagator.Getter; -import io.opentelemetry.instrumentation.api.tracer.RpcServerTracer; -import java.lang.reflect.Method; - -public class RmiServerTracer extends RpcServerTracer { - private static final RmiServerTracer TRACER = new RmiServerTracer(); - - public static RmiServerTracer tracer() { - return TRACER; - } - - public Span startSpan(Method method, Context context) { - String serviceName = method.getDeclaringClass().getName(); - String methodName = method.getName(); - - SpanBuilder spanBuilder = - tracer.spanBuilder(serviceName + "/" + methodName).setSpanKind(SERVER).setParent(context); - spanBuilder.setAttribute(SemanticAttributes.RPC_SYSTEM, "java_rmi"); - spanBuilder.setAttribute(SemanticAttributes.RPC_SERVICE, serviceName); - spanBuilder.setAttribute(SemanticAttributes.RPC_METHOD, methodName); - - return spanBuilder.startSpan(); - } - - @Override - protected Getter getGetter() { - return null; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.javaagent.rmi"; - } -} diff --git a/instrumentation/rmi/src/test/groovy/RmiTest.groovy b/instrumentation/rmi/src/test/groovy/RmiTest.groovy deleted file mode 100644 index c011f04cc7..0000000000 --- a/instrumentation/rmi/src/test/groovy/RmiTest.groovy +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import static io.opentelemetry.api.trace.Span.Kind.CLIENT -import static io.opentelemetry.api.trace.Span.Kind.SERVER -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.basicSpan -import static io.opentelemetry.instrumentation.test.utils.TraceUtils.runUnderTrace - -import io.opentelemetry.api.trace.attributes.SemanticAttributes -import io.opentelemetry.instrumentation.test.AgentTestRunner -import io.opentelemetry.instrumentation.test.utils.PortUtils -import java.rmi.registry.LocateRegistry -import java.rmi.server.UnicastRemoteObject -import rmi.app.Greeter -import rmi.app.Server -import rmi.app.ServerLegacy - -class RmiTest extends AgentTestRunner { - def registryPort = PortUtils.randomOpenPort() - def serverRegistry = LocateRegistry.createRegistry(registryPort) - def clientRegistry = LocateRegistry.getRegistry("localhost", registryPort) - - def cleanup() { - UnicastRemoteObject.unexportObject(serverRegistry, true) - } - - def "Client call creates spans"() { - setup: - def server = new Server() - serverRegistry.rebind(Server.RMI_ID, server) - - when: - def response = runUnderTrace("parent") { - def client = (Greeter) clientRegistry.lookup(Server.RMI_ID) - return client.hello("you") - } - - then: - response.contains("Hello you") - assertTraces(1) { - trace(0, 3) { - basicSpan(it, 0, "parent") - span(1) { - name "rmi.app.Greeter/hello" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.RPC_SYSTEM.key()}" "java_rmi" - "${SemanticAttributes.RPC_SERVICE.key()}" "rmi.app.Greeter" - "${SemanticAttributes.RPC_METHOD.key()}" "hello" - } - } - span(2) { - name "rmi.app.Server/hello" - kind SERVER - attributes { - "${SemanticAttributes.RPC_SYSTEM.key()}" "java_rmi" - "${SemanticAttributes.RPC_SERVICE.key()}" "rmi.app.Server" - "${SemanticAttributes.RPC_METHOD.key()}" "hello" - } - } - } - } - - cleanup: - serverRegistry.unbind("Server") - } - - def "Calling server builtin methods doesn't create server spans"() { - setup: - def server = new Server() - serverRegistry.rebind(Server.RMI_ID, server) - - when: - server.equals(new Server()) - server.getRef() - server.hashCode() - server.toString() - server.getClass() - - then: - assertTraces(0) {} - - cleanup: - serverRegistry.unbind("Server") - } - - def "Service throws exception and its propagated to spans"() { - setup: - def server = new Server() - serverRegistry.rebind(Server.RMI_ID, server) - - when: - runUnderTrace("parent") { - def client = (Greeter) clientRegistry.lookup(Server.RMI_ID) - client.exceptional() - } - - then: - def thrownException = thrown(RuntimeException) - assertTraces(1) { - trace(0, 3) { - basicSpan(it, 0, "parent", null, thrownException) - span(1) { - name "rmi.app.Greeter/exceptional" - kind CLIENT - childOf span(0) - errored true - errorEvent(RuntimeException, String) - attributes { - "${SemanticAttributes.RPC_SYSTEM.key()}" "java_rmi" - "${SemanticAttributes.RPC_SERVICE.key()}" "rmi.app.Greeter" - "${SemanticAttributes.RPC_METHOD.key()}" "exceptional" - - } - } - span(2) { - name "rmi.app.Server/exceptional" - kind SERVER - errored true - errorEvent(RuntimeException, String) - attributes { - "${SemanticAttributes.RPC_SYSTEM.key()}" "java_rmi" - "${SemanticAttributes.RPC_SERVICE.key()}" "rmi.app.Server" - "${SemanticAttributes.RPC_METHOD.key()}" "exceptional" - } - } - } - } - - cleanup: - serverRegistry.unbind("Server") - } - - def "Client call using ServerLegacy_stub creates spans"() { - setup: - def server = new ServerLegacy() - serverRegistry.rebind(ServerLegacy.RMI_ID, server) - - when: - def response = runUnderTrace("parent") { - def client = (Greeter) clientRegistry.lookup(ServerLegacy.RMI_ID) - return client.hello("you") - } - - then: - response.contains("Hello you") - assertTraces(1) { - trace(0, 3) { - basicSpan(it, 0, "parent") - span(1) { - name "rmi.app.Greeter/hello" - kind CLIENT - childOf span(0) - attributes { - "${SemanticAttributes.RPC_SYSTEM.key()}" "java_rmi" - "${SemanticAttributes.RPC_SERVICE.key()}" "rmi.app.Greeter" - "${SemanticAttributes.RPC_METHOD.key()}" "hello" - } - } - span(2) { - childOf span(1) - name "rmi.app.ServerLegacy/hello" - kind SERVER - attributes { - "${SemanticAttributes.RPC_SYSTEM.key()}" "java_rmi" - "${SemanticAttributes.RPC_SERVICE.key()}" "rmi.app.ServerLegacy" - "${SemanticAttributes.RPC_METHOD.key()}" "hello" - } - } - } - } - - cleanup: - serverRegistry.unbind(ServerLegacy.RMI_ID) - } -} diff --git a/instrumentation/rmi/src/test/java/rmi/app/Greeter.java b/instrumentation/rmi/src/test/java/rmi/app/Greeter.java deleted file mode 100644 index 57c715b101..0000000000 --- a/instrumentation/rmi/src/test/java/rmi/app/Greeter.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package rmi.app; - -import java.rmi.Remote; -import java.rmi.RemoteException; - -public interface Greeter extends Remote { - String hello(String name) throws RemoteException; - - void exceptional() throws RemoteException, RuntimeException; -} diff --git a/instrumentation/rmi/src/test/java/rmi/app/Server.java b/instrumentation/rmi/src/test/java/rmi/app/Server.java deleted file mode 100644 index 6ba5de00c9..0000000000 --- a/instrumentation/rmi/src/test/java/rmi/app/Server.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package rmi.app; - -import java.rmi.RemoteException; -import java.rmi.server.UnicastRemoteObject; - -public class Server extends UnicastRemoteObject implements Greeter { - public static String RMI_ID = Server.class.getSimpleName(); - - private static final long serialVersionUID = 1L; - - public Server() throws RemoteException { - super(); - } - - @Override - public String hello(String name) { - return someMethod(name); - } - - public String someMethod(String name) { - return "Hello " + name; - } - - @Override - public void exceptional() throws RuntimeException { - throw new RuntimeException("expected"); - } -} diff --git a/instrumentation/rmi/src/test/java/rmi/app/ServerLegacy.java b/instrumentation/rmi/src/test/java/rmi/app/ServerLegacy.java deleted file mode 100644 index 5defe9b4a2..0000000000 --- a/instrumentation/rmi/src/test/java/rmi/app/ServerLegacy.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package rmi.app; - -import java.rmi.RemoteException; -import java.rmi.server.UnicastRemoteObject; - -public class ServerLegacy extends UnicastRemoteObject implements Greeter { - static String RMI_ID = ServerLegacy.class.getSimpleName(); - - private static final long serialVersionUID = 1L; - - public ServerLegacy() throws RemoteException { - super(); - } - - @Override - public String hello(String name) { - return "Hello " + name; - } - - @Override - public void exceptional() throws RuntimeException { - throw new RuntimeException("expected"); - } -} diff --git a/instrumentation/scala-executors/javaagent/scala-executors-javaagent.gradle b/instrumentation/scala-executors/javaagent/scala-executors-javaagent.gradle index 4fa13c171c..b12b4a5a6b 100644 --- a/instrumentation/scala-executors/javaagent/scala-executors-javaagent.gradle +++ b/instrumentation/scala-executors/javaagent/scala-executors-javaagent.gradle @@ -30,7 +30,7 @@ dependencies { latestDepTestLibrary group: 'org.scala-lang', name: 'scala-library', version: '2.11.+' - slickTestImplementation project(':instrumentation:jdbc') + slickTestImplementation project(':instrumentation:jdbc:javaagent') slickTestImplementation deps.scala slickTestImplementation group: 'com.typesafe.slick', name: 'slick_2.11', version: '3.2.0' slickTestImplementation group: 'com.h2database', name: 'h2', version: '1.4.197' diff --git a/instrumentation/servlet/glassfish-testing/glassfish-testing.gradle b/instrumentation/servlet/glassfish-testing/glassfish-testing.gradle index fe94e78fee..e4a9bdb4d2 100644 --- a/instrumentation/servlet/glassfish-testing/glassfish-testing.gradle +++ b/instrumentation/servlet/glassfish-testing/glassfish-testing.gradle @@ -8,7 +8,7 @@ apply from: "$rootDir/gradle/instrumentation.gradle" dependencies { testImplementation project(':instrumentation:servlet:servlet-3.0:javaagent') - testImplementation project(':instrumentation:grizzly-2.0') + testImplementation project(':instrumentation:grizzly-2.0:javaagent') testLibrary group: 'org.glassfish.main.extras', name: 'glassfish-embedded-all', version: '4.0' } diff --git a/instrumentation/servlet/servlet-3.0/javaagent/servlet-3.0-javaagent.gradle b/instrumentation/servlet/servlet-3.0/javaagent/servlet-3.0-javaagent.gradle index 69f5deed85..5bfdd69dfc 100644 --- a/instrumentation/servlet/servlet-3.0/javaagent/servlet-3.0-javaagent.gradle +++ b/instrumentation/servlet/servlet-3.0/javaagent/servlet-3.0-javaagent.gradle @@ -18,7 +18,7 @@ dependencies { compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' api(project(':instrumentation-core:servlet-2.2')) - testImplementation project(':instrumentation:jetty-8.0') + testImplementation project(':instrumentation:jetty-8.0:javaagent') testImplementation(project(':testing-common')) { exclude group: 'org.eclipse.jetty', module: 'jetty-server' diff --git a/instrumentation/spark-2.3/javaagent/spark-2.3-javaagent.gradle b/instrumentation/spark-2.3/javaagent/spark-2.3-javaagent.gradle index c3dc1a37eb..ab268f1d18 100644 --- a/instrumentation/spark-2.3/javaagent/spark-2.3-javaagent.gradle +++ b/instrumentation/spark-2.3/javaagent/spark-2.3-javaagent.gradle @@ -13,7 +13,7 @@ muzzle { dependencies { library group: 'com.sparkjava', name: 'spark-core', version: '2.3' - testImplementation project(':instrumentation:jetty-8.0') + testImplementation project(':instrumentation:jetty-8.0:javaagent') testLibrary group: 'com.sparkjava', name: 'spark-core', version: '2.4' } diff --git a/instrumentation/spring/spring-data-1.8/javaagent/spring-data-1.8-javaagent.gradle b/instrumentation/spring/spring-data-1.8/javaagent/spring-data-1.8-javaagent.gradle index a73f5196f8..79d286e755 100644 --- a/instrumentation/spring/spring-data-1.8/javaagent/spring-data-1.8-javaagent.gradle +++ b/instrumentation/spring/spring-data-1.8/javaagent/spring-data-1.8-javaagent.gradle @@ -30,7 +30,7 @@ dependencies { testLibrary group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.8.0.RELEASE' // JPA dependencies - testImplementation project(':instrumentation:jdbc') + testImplementation project(':instrumentation:jdbc:javaagent') testImplementation group: 'com.mysema.querydsl', name: 'querydsl-jpa', version: '3.7.4' testImplementation group: 'org.hsqldb', name: 'hsqldb', version: '2.0.0' testImplementation group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.3.0.Final' diff --git a/instrumentation/spring/spring-webflux-5.0/javaagent/spring-webflux-5.0-javaagent.gradle b/instrumentation/spring/spring-webflux-5.0/javaagent/spring-webflux-5.0-javaagent.gradle index b0c8d718ba..6de8a47759 100644 --- a/instrumentation/spring/spring-webflux-5.0/javaagent/spring-webflux-5.0-javaagent.gradle +++ b/instrumentation/spring/spring-webflux-5.0/javaagent/spring-webflux-5.0-javaagent.gradle @@ -41,8 +41,8 @@ dependencies { compileOnly group: 'org.springframework', name: 'spring-webflux', version: '5.0.0.RELEASE' compileOnly group: 'io.projectreactor.ipc', name: 'reactor-netty', version: '0.7.0.RELEASE' - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:reactor-3.1') + testImplementation project(':instrumentation:netty:netty-4.1:javaagent') + testImplementation project(':instrumentation:reactor-3.1:javaagent') testLibrary group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: '2.0.0.RELEASE' testLibrary group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE' diff --git a/instrumentation/struts-2.3/javaagent/struts-2.3-javaagent.gradle b/instrumentation/struts-2.3/javaagent/struts-2.3-javaagent.gradle index f077489915..3a986b4bdb 100644 --- a/instrumentation/struts-2.3/javaagent/struts-2.3-javaagent.gradle +++ b/instrumentation/struts-2.3/javaagent/struts-2.3-javaagent.gradle @@ -24,6 +24,6 @@ dependencies { testRuntime group: 'javax.servlet', name: 'jsp-api', version: '2.0' testImplementation project(":instrumentation:servlet:servlet-3.0:javaagent") - testImplementation project(':instrumentation:jetty-8.0') + testImplementation project(':instrumentation:jetty-8.0:javaagent') } diff --git a/instrumentation/twilio-6.6/javaagent/twilio-6.6-javaagent.gradle b/instrumentation/twilio-6.6/javaagent/twilio-6.6-javaagent.gradle index 7fc34897aa..366daf7e54 100644 --- a/instrumentation/twilio-6.6/javaagent/twilio-6.6-javaagent.gradle +++ b/instrumentation/twilio-6.6/javaagent/twilio-6.6-javaagent.gradle @@ -13,7 +13,7 @@ dependencies { library group: 'com.twilio.sdk', name: 'twilio', version: '6.6.9' // included to make sure the apache httpclient nested spans are suppressed - testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-4.0') + testImplementation project(':instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent') latestDepTestLibrary group: 'com.twilio.sdk', name: 'twilio', version: '7.+' } diff --git a/instrumentation/vertx-reactive-3.5/javaagent/vertx-reactive-3.5-javaagent.gradle b/instrumentation/vertx-reactive-3.5/javaagent/vertx-reactive-3.5-javaagent.gradle index 8f0e943384..2aab30e39c 100644 --- a/instrumentation/vertx-reactive-3.5/javaagent/vertx-reactive-3.5-javaagent.gradle +++ b/instrumentation/vertx-reactive-3.5/javaagent/vertx-reactive-3.5-javaagent.gradle @@ -15,8 +15,8 @@ dependencies { library group: 'io.vertx', name: 'vertx-web', version: vertxVersion library group: 'io.vertx', name: 'vertx-rx-java2', version: vertxVersion - testImplementation project(':instrumentation:jdbc') - testImplementation project(':instrumentation:netty:netty-4.1') + testImplementation project(':instrumentation:jdbc:javaagent') + testImplementation project(':instrumentation:netty:netty-4.1:javaagent') testImplementation project(':instrumentation:vertx-web-3.0') testLibrary group: 'io.vertx', name: 'vertx-web-client', version: vertxVersion diff --git a/instrumentation/vertx-web-3.0/vertx-web-3.0.gradle b/instrumentation/vertx-web-3.0/vertx-web-3.0.gradle index c07a34b04b..c1e1bbcf8d 100644 --- a/instrumentation/vertx-web-3.0/vertx-web-3.0.gradle +++ b/instrumentation/vertx-web-3.0/vertx-web-3.0.gradle @@ -14,9 +14,9 @@ dependencies { library group: 'io.vertx', name: 'vertx-web', version: vertxVersion //We need both version as different versions of Vert.x use different versions of Netty - testImplementation project(':instrumentation:netty:netty-4.0') - testImplementation project(':instrumentation:netty:netty-4.1') - testImplementation project(':instrumentation:jdbc') + testImplementation project(':instrumentation:netty:netty-4.0:javaagent') + testImplementation project(':instrumentation:netty:netty-4.1:javaagent') + testImplementation project(':instrumentation:jdbc:javaagent') testImplementation group: 'io.vertx', name: 'vertx-jdbc-client', version: vertxVersion diff --git a/settings.gradle b/settings.gradle index a96b734249..1131b48fd0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -53,122 +53,122 @@ include ':utils:test-utils' // smoke tests include ':smoke-tests' -include ':instrumentation:akka-actor-2.5' -include ':instrumentation:akka-http-10.0' -include ':instrumentation:apache-camel-2.20' -include ':instrumentation:apache-httpasyncclient-4.0' -include ':instrumentation:apache-httpclient:apache-httpclient-2.0' -include ':instrumentation:apache-httpclient:apache-httpclient-4.0' +include ':instrumentation:akka-actor-2.5:javaagent' +include ':instrumentation:akka-http-10.0:javaagent' +include ':instrumentation:apache-camel-2.20:javaagent' +include ':instrumentation:apache-httpasyncclient-4.0:javaagent' +include ':instrumentation:apache-httpclient:apache-httpclient-2.0:javaagent' +include ':instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent' include ':instrumentation:armeria-1.0:javaagent' include ':instrumentation:armeria-1.0:library' include ':instrumentation:armeria-1.0:testing' -include ':instrumentation:async-http-client-1.9' +include ':instrumentation:async-http-client-1.9:javaagent' include ':instrumentation:aws-lambda-1.0:javaagent' include ':instrumentation:aws-lambda-1.0:library' include ':instrumentation:aws-lambda-1.0:testing' -include ':instrumentation:aws-sdk:aws-sdk-1.11' +include ':instrumentation:aws-sdk:aws-sdk-1.11:javaagent' include ':instrumentation:aws-sdk:aws-sdk-2.2:javaagent' include ':instrumentation:aws-sdk:aws-sdk-2.2:library' include ':instrumentation:aws-sdk:aws-sdk-2.2:testing' -include ':instrumentation:cassandra:cassandra-3.0' -include ':instrumentation:cassandra:cassandra-4.0' +include ':instrumentation:cassandra:cassandra-3.0:javaagent' +include ':instrumentation:cassandra:cassandra-4.0:javaagent' include ':instrumentation:cdi-testing' -include ':instrumentation:classloaders' -include ':instrumentation:classloaders:jboss-testing' -include ':instrumentation:classloaders:osgi-testing' -include ':instrumentation:classloaders:tomcat-testing' -include ':instrumentation:couchbase:couchbase-2.0' -include ':instrumentation:couchbase:couchbase-2.6' +include ':instrumentation:classloaders:javaagent' +include ':instrumentation:classloaders:javaagent:jboss-testing' +include ':instrumentation:classloaders:javaagent:osgi-testing' +include ':instrumentation:classloaders:javaagent:tomcat-testing' +include ':instrumentation:couchbase:couchbase-2.0:javaagent' +include ':instrumentation:couchbase:couchbase-2.6:javaagent' include ':instrumentation:couchbase:couchbase-testing' -include ':instrumentation:dropwizard-views-0.7' +include ':instrumentation:dropwizard-views-0.7:javaagent' include ':instrumentation:dropwizard-testing' -include ':instrumentation:elasticsearch:elasticsearch-rest-common' -include ':instrumentation:elasticsearch:elasticsearch-rest-5.0' -include ':instrumentation:elasticsearch:elasticsearch-rest-6.4' -include ':instrumentation:elasticsearch:elasticsearch-transport-common' -include ':instrumentation:elasticsearch:elasticsearch-transport-5.0' -include ':instrumentation:elasticsearch:elasticsearch-transport-5.3' -include ':instrumentation:elasticsearch:elasticsearch-transport-6.0' -include ':instrumentation:executors' -include ':instrumentation:external-annotations' -include ':instrumentation:finatra-2.9' -include ':instrumentation:geode-1.4' -include ':instrumentation:google-http-client-1.19' -include ':instrumentation:grizzly-2.0' +include ':instrumentation:elasticsearch:elasticsearch-rest-common:javaagent' +include ':instrumentation:elasticsearch:elasticsearch-rest-5.0:javaagent' +include ':instrumentation:elasticsearch:elasticsearch-rest-6.4:javaagent' +include ':instrumentation:elasticsearch:elasticsearch-transport-common:javaagent' +include ':instrumentation:elasticsearch:elasticsearch-transport-5.0:javaagent' +include ':instrumentation:elasticsearch:elasticsearch-transport-5.3:javaagent' +include ':instrumentation:elasticsearch:elasticsearch-transport-6.0:javaagent' +include ':instrumentation:executors:javaagent' +include ':instrumentation:external-annotations:javaagent' +include ':instrumentation:finatra-2.9:javaagent' +include ':instrumentation:geode-1.4:javaagent' +include ':instrumentation:google-http-client-1.19:javaagent' +include ':instrumentation:grizzly-2.0:javaagent' include ':instrumentation:grpc-1.5:javaagent' include ':instrumentation:grpc-1.5:library' include ':instrumentation:grpc-1.5:testing' -include ':instrumentation:guava-10.0' -include ':instrumentation:hibernate:hibernate-3.3' -include ':instrumentation:hibernate:hibernate-4.0' -include ':instrumentation:hibernate:hibernate-4.3' -include ':instrumentation:hibernate:hibernate-common' -include ':instrumentation:http-url-connection' -include ':instrumentation:hystrix-1.4' -include ':instrumentation:java-httpclient' -include ':instrumentation:jaxrs:jaxrs-1.0' -include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common' -include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0' -include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.0' -include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.1' +include ':instrumentation:guava-10.0:javaagent' +include ':instrumentation:hibernate:hibernate-3.3:javaagent' +include ':instrumentation:hibernate:hibernate-4.0:javaagent' +include ':instrumentation:hibernate:hibernate-4.3:javaagent' +include ':instrumentation:hibernate:hibernate-common:javaagent' +include ':instrumentation:http-url-connection:javaagent' +include ':instrumentation:hystrix-1.4:javaagent' +include ':instrumentation:java-httpclient:javaagent' +include ':instrumentation:jaxrs:jaxrs-1.0:javaagent' +include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent' +include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0:javaagent' +include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.0:javaagent' +include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.1:javaagent' include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing' -include ':instrumentation:jaxrs-client:jaxrs-client-1.1' -include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-common' -include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-jersey-2.0' -include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-resteasy-2.0' -include ':instrumentation:jdbc' -include ':instrumentation:jedis:jedis-1.4' -include ':instrumentation:jedis:jedis-3.0' -include ':instrumentation:jetty-8.0' -include ':instrumentation:jms-1.1' -include ':instrumentation:jsp-2.3' -include ':instrumentation:kafka-clients-0.11' -include ':instrumentation:kafka-streams-0.11' -include ':instrumentation:khttp-0.1' -include ':instrumentation:kotlinx-coroutines' -include ':instrumentation:kubernetes-client-7.0' -include ':instrumentation:lettuce:lettuce-common' -include ':instrumentation:lettuce:lettuce-4.0' -include ':instrumentation:lettuce:lettuce-5.0' -include ':instrumentation:lettuce:lettuce-5.1' -include ':instrumentation:log4j:log4j-1.2' -include ':instrumentation:log4j:log4j-2.7' +include ':instrumentation:jaxrs-client:jaxrs-client-1.1:javaagent' +include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-common:javaagent' +include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-jersey-2.0:javaagent' +include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-resteasy-2.0:javaagent' +include ':instrumentation:jdbc:javaagent' +include ':instrumentation:jedis:jedis-1.4:javaagent' +include ':instrumentation:jedis:jedis-3.0:javaagent' +include ':instrumentation:jetty-8.0:javaagent' +include ':instrumentation:jms-1.1:javaagent' +include ':instrumentation:jsp-2.3:javaagent' +include ':instrumentation:kafka-clients-0.11:javaagent' +include ':instrumentation:kafka-streams-0.11:javaagent' +include ':instrumentation:khttp-0.1:javaagent' +include ':instrumentation:kotlinx-coroutines:javaagent' +include ':instrumentation:kubernetes-client-7.0:javaagent' +include ':instrumentation:lettuce:lettuce-common:javaagent' +include ':instrumentation:lettuce:lettuce-4.0:javaagent' +include ':instrumentation:lettuce:lettuce-5.0:javaagent' +include ':instrumentation:lettuce:lettuce-5.1:javaagent' +include ':instrumentation:log4j:log4j-1.2:javaagent' +include ':instrumentation:log4j:log4j-2.7:javaagent' include ':instrumentation:log4j:log4j-2.13.2:javaagent' include ':instrumentation:log4j:log4j-2.13.2:library' include ':instrumentation:log4j:log4j-2-testing' include ':instrumentation:logback:logback-1.0:javaagent' include ':instrumentation:logback:logback-1.0:library' include ':instrumentation:logback:logback-1.0:testing' -include ':instrumentation:methods' -include ':instrumentation:mongo:mongo-3.1' -include ':instrumentation:mongo:mongo-3.7' -include ':instrumentation:mongo:mongo-async-3.3' -include ':instrumentation:mongo:mongo-common' +include ':instrumentation:methods:javaagent' +include ':instrumentation:mongo:mongo-3.1:javaagent' +include ':instrumentation:mongo:mongo-3.7:javaagent' +include ':instrumentation:mongo:mongo-async-3.3:javaagent' +include ':instrumentation:mongo:mongo-common:javaagent' include ':instrumentation:mongo:mongo-testing' -include ':instrumentation:netty:netty-3.8' -include ':instrumentation:netty:netty-4.0' -include ':instrumentation:netty:netty-4.1' -include ':instrumentation:okhttp:okhttp-2.2' -include ':instrumentation:okhttp:okhttp-3.0' -include ':instrumentation:opentelemetry-annotations-1.0' -include ':instrumentation:opentelemetry-api-1.0' +include ':instrumentation:netty:netty-3.8:javaagent' +include ':instrumentation:netty:netty-4.0:javaagent' +include ':instrumentation:netty:netty-4.1:javaagent' +include ':instrumentation:okhttp:okhttp-2.2:javaagent' +include ':instrumentation:okhttp:okhttp-3.0:javaagent' +include ':instrumentation:opentelemetry-annotations-1.0:javaagent' +include ':instrumentation:opentelemetry-api-1.0:javaagent' include ':instrumentation:oshi:javaagent' include ':instrumentation:oshi:library' -include ':instrumentation:play:play-2.3' -include ':instrumentation:play:play-2.4' -include ':instrumentation:play:play-2.6' -include ':instrumentation:play-ws:play-ws-1.0' -include ':instrumentation:play-ws:play-ws-2.0' -include ':instrumentation:play-ws:play-ws-2.1' -include ':instrumentation:play-ws:play-ws-common' +include ':instrumentation:play:play-2.3:javaagent' +include ':instrumentation:play:play-2.4:javaagent' +include ':instrumentation:play:play-2.6:javaagent' +include ':instrumentation:play-ws:play-ws-1.0:javaagent' +include ':instrumentation:play-ws:play-ws-2.0:javaagent' +include ':instrumentation:play-ws:play-ws-2.1:javaagent' +include ':instrumentation:play-ws:play-ws-common:javaagent' include ':instrumentation:play-ws:play-ws-testing' -include ':instrumentation:rabbitmq-2.7' -include ':instrumentation:ratpack-1.4' -include ':instrumentation:reactor-3.1' -include ':instrumentation:reactor-netty-0.9' -include ':instrumentation:rediscala-1.8' -include ':instrumentation:redisson-3.0' -include ':instrumentation:rmi' +include ':instrumentation:rabbitmq-2.7:javaagent' +include ':instrumentation:ratpack-1.4:javaagent' +include ':instrumentation:reactor-3.1:javaagent' +include ':instrumentation:reactor-netty-0.9:javaagent' +include ':instrumentation:rediscala-1.8:javaagent' +include ':instrumentation:redisson-3.0:javaagent' +include ':instrumentation:rmi:javaagent' include ':instrumentation:runtime-metrics:library' include ':instrumentation:rxjava-1.0:library' include ':instrumentation:scala-executors:javaagent' diff --git a/testing-common/testing-common.gradle b/testing-common/testing-common.gradle index 46e85f8a17..52b11177ee 100644 --- a/testing-common/testing-common.gradle +++ b/testing-common/testing-common.gradle @@ -48,7 +48,7 @@ dependencies { api deps.groovy testImplementation deps.opentelemetryAutoAnnotations - testImplementation project(':instrumentation:external-annotations') + testImplementation project(':instrumentation:external-annotations:javaagent') testImplementation group: 'cglib', name: 'cglib', version: '3.2.5' // test instrumenting java 1.1 bytecode