Browse Source

Fix the main branch history (#8817)

Mateusz Rzeszutek 1 năm trước cách đây
mục cha
commit
9e37e724dc
31 tập tin đã thay đổi với 408 bổ sung302 xóa
  1. 1 1
      benchmark-overhead-jmh/build.gradle.kts
  2. 2 2
      conventions/build.gradle.kts
  3. 2 2
      dependencyManagement/build.gradle.kts
  4. 1 1
      examples/distro/build.gradle
  5. 80 0
      instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/network/ClientAttributesExtractorInetSocketAddressTest.java
  6. 36 13
      instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts
  7. 39 0
      instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AbstractAwsSdkInstrumentationModule.java
  8. 2 33
      instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkInstrumentationModule.java
  9. 5 23
      instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/SqsInstrumentationModule.java
  10. 1 0
      instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts
  11. 33 11
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsAccess.java
  12. 3 3
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsAdviceBridge.java
  13. 45 6
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsImpl.java
  14. 0 122
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsReceiveMessageRequestAccess.java
  15. 0 23
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsSendMessageRequestAccess.java
  16. 5 45
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingExecutionInterceptor.java
  17. 1 1
      instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/Aws2ClientTest.groovy
  18. 39 0
      instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy
  19. 7 6
      instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2SqsTracingTest.groovy
  20. 2 0
      instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java
  21. 9 0
      instrumentation/log4j/log4j-appender-2.17/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/Log4j2Test.java
  22. 3 3
      instrumentation/log4j/log4j-appender-2.17/library/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppenderConfigTestBase.java
  23. 18 0
      instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/BaseClusterInstrumentation.java
  24. 43 0
      instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/DefaultConnectionPoolTaskInstrumentation.java
  25. 1 0
      instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/MongoClientInstrumentationModule.java
  26. 27 0
      instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/TaskWrapper.java
  27. 0 2
      instrumentation/resources/library/src/test/resources/docker_proc_self_mountinfo
  28. 0 2
      instrumentation/resources/library/src/test/resources/podman_proc_self_mountinfo
  29. 1 1
      settings.gradle.kts
  30. 1 1
      smoke-tests/images/fake-backend/build.gradle.kts
  31. 1 1
      testing/armeria-shaded-for-testing/build.gradle.kts

+ 1 - 1
benchmark-overhead-jmh/build.gradle.kts

@@ -8,7 +8,7 @@ plugins {
 }
 
 dependencies {
-  jmhImplementation("org.springframework.boot:spring-boot-starter-web:3.1.0")
+  jmhImplementation("org.springframework.boot:spring-boot-starter-web:3.1.1")
 }
 
 tasks {

+ 2 - 2
conventions/build.gradle.kts

@@ -59,8 +59,8 @@ dependencies {
   implementation("gradle.plugin.com.google.protobuf:protobuf-gradle-plugin:0.8.18")
   implementation("com.github.johnrengelman:shadow:8.1.1")
   implementation("org.apache.httpcomponents:httpclient:4.5.14")
-  implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.13.3")
-  implementation("org.owasp:dependency-check-gradle:8.2.1")
+  implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.13.4")
+  implementation("org.owasp:dependency-check-gradle:8.3.1")
   implementation("ru.vyarus:gradle-animalsniffer-plugin:1.7.0")
   // When updating, also update dependencyManagement/build.gradle.kts
   implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.14.5")

+ 2 - 2
dependencyManagement/build.gradle.kts

@@ -84,10 +84,10 @@ val DEPENDENCIES = listOf(
   "com.github.stefanbirkner:system-lambda:1.2.1",
   "com.github.stefanbirkner:system-rules:1.19.0",
   "uk.org.webcompere:system-stubs-jupiter:2.0.2",
-  "com.uber.nullaway:nullaway:0.10.10",
+  "com.uber.nullaway:nullaway:0.10.11",
   "commons-beanutils:commons-beanutils:1.9.4",
   "commons-cli:commons-cli:1.5.0",
-  "commons-codec:commons-codec:1.15",
+  "commons-codec:commons-codec:1.16.0",
   "commons-collections:commons-collections:3.2.2",
   "commons-digester:commons-digester:2.1",
   "commons-fileupload:commons-fileupload:1.5",

+ 1 - 1
examples/distro/build.gradle

@@ -70,7 +70,7 @@ subprojects {
     implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:${versions.opentelemetryJavaagent}"))
     implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:${versions.opentelemetryJavaagentAlpha}"))
 
-    testImplementation("org.mockito:mockito-core:5.3.1")
+    testImplementation("org.mockito:mockito-core:5.4.0")
     testImplementation(enforcedPlatform("org.junit:junit-bom:${versions.junit}"))
     testImplementation("org.junit.jupiter:junit-jupiter-api:${versions.junit}")
     testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${versions.junit}")

+ 80 - 0
instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/network/ClientAttributesExtractorInetSocketAddressTest.java

@@ -0,0 +1,80 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.api.instrumenter.network;
+
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.AttributesBuilder;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
+import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
+import java.net.InetSocketAddress;
+import javax.annotation.Nullable;
+import org.junit.jupiter.api.Test;
+
+class ClientAttributesExtractorInetSocketAddressTest {
+
+  static class TestClientAttributesGetter
+      implements ClientAttributesGetter<InetSocketAddress, Void> {
+
+    @Nullable
+    @Override
+    public String getClientAddress(InetSocketAddress request) {
+      // covered in ClientAttributesExtractorTest
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public Integer getClientPort(InetSocketAddress request) {
+      // covered in ClientAttributesExtractorTest
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public InetSocketAddress getClientInetSocketAddress(
+        InetSocketAddress request, @Nullable Void response) {
+      return request;
+    }
+  }
+
+  @Test
+  void fullAddress() {
+    InetSocketAddress address = new InetSocketAddress("api.github.com", 456);
+    assertThat(address.getAddress().getHostAddress()).isNotNull();
+
+    AttributesExtractor<InetSocketAddress, Void> extractor =
+        ClientAttributesExtractor.create(new TestClientAttributesGetter());
+
+    AttributesBuilder startAttributes = Attributes.builder();
+    extractor.onStart(startAttributes, Context.root(), address);
+    assertThat(startAttributes.build()).isEmpty();
+
+    AttributesBuilder endAttributes = Attributes.builder();
+    extractor.onEnd(endAttributes, Context.root(), address, null, null);
+    assertThat(endAttributes.build())
+        .containsOnly(
+            entry(NetworkAttributes.CLIENT_SOCKET_ADDRESS, address.getAddress().getHostAddress()),
+            entry(NetworkAttributes.CLIENT_SOCKET_PORT, 456L));
+  }
+
+  @Test
+  void noAttributes() {
+    AttributesExtractor<InetSocketAddress, Void> extractor =
+        ClientAttributesExtractor.create(new TestClientAttributesGetter());
+
+    AttributesBuilder startAttributes = Attributes.builder();
+    extractor.onStart(startAttributes, Context.root(), null);
+    assertThat(startAttributes.build()).isEmpty();
+
+    AttributesBuilder endAttributes = Attributes.builder();
+    extractor.onEnd(endAttributes, Context.root(), null, null, null);
+    assertThat(endAttributes.build()).isEmpty();
+  }
+}

+ 36 - 13
instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts

@@ -15,9 +15,23 @@ muzzle {
     // several software.amazon.awssdk artifacts are missing for this version
     skip("2.17.200")
   }
-}
 
-muzzle {
+  fail {
+    group.set("software.amazon.awssdk")
+    module.set("aws-core")
+    versions.set("[2.2.0,)")
+    // Used by all SDK services, the only case it isn't is an SDK extension such as a custom HTTP
+    // client, which is not target of instrumentation anyways.
+    extraDependency("software.amazon.awssdk:protocol-core")
+
+    // "fail" asserts that *all* the instrumentation modules fail to load, but the core one is
+    // actually expected to succeed, so exclude it from checks.
+    excludeInstrumentationName("aws-sdk-2.2-core")
+
+    // several software.amazon.awssdk artifacts are missing for this version
+    skip("2.17.200")
+  }
+
   pass {
     group.set("software.amazon.awssdk")
     module.set("sqs")
@@ -53,17 +67,26 @@ dependencies {
   latestDepTestLibrary("software.amazon.awssdk:sqs:+")
 }
 
-tasks.withType<Test>().configureEach {
-  systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
-  // TODO run tests both with and without experimental span attributes, with & without extra propagation
-  systemProperties(mapOf(
-    "otel.instrumentation.aws-sdk.experimental-span-attributes" to "true",
-    "otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging" to "true",
-  ))
-}
+tasks {
+  val testExperimentalSqs by registering(Test::class) {
+    group = "verification"
+
+    systemProperty("otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", "true")
+  }
+
+  check {
+    dependsOn(testExperimentalSqs)
+  }
+
+  withType<Test>().configureEach {
+    systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
+    // TODO run tests both with and without experimental span attributes
+    systemProperty("otel.instrumentation.aws-sdk.experimental-span-attributes", "true")
+  }
 
-tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>().configureEach {
-  mergeServiceFiles {
-    include("software/amazon/awssdk/global/handlers/execution.interceptors")
+  withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>().configureEach {
+    mergeServiceFiles {
+      include("software/amazon/awssdk/global/handlers/execution.interceptors")
+    }
   }
 }

+ 39 - 0
instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AbstractAwsSdkInstrumentationModule.java

@@ -5,7 +5,16 @@
 
 package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2;
 
+import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
+import static java.util.Collections.singletonList;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
 import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
+import java.util.List;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
 
 abstract class AbstractAwsSdkInstrumentationModule extends InstrumentationModule {
 
@@ -17,4 +26,34 @@ abstract class AbstractAwsSdkInstrumentationModule extends InstrumentationModule
   public boolean isHelperClass(String className) {
     return className.startsWith("io.opentelemetry.contrib.awsxray.");
   }
+
+  @Override
+  public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
+    // We don't actually transform it but want to make sure we only apply the instrumentation when
+    // our key dependency is present.
+    return hasClassesNamed("software.amazon.awssdk.core.interceptor.ExecutionInterceptor");
+  }
+
+  @Override
+  public List<TypeInstrumentation> typeInstrumentations() {
+    return singletonList(new ResourceInjectingTypeInstrumentation());
+  }
+
+  abstract void doTransform(TypeTransformer transformer);
+
+  // A type instrumentation is needed to trigger resource injection.
+  public class ResourceInjectingTypeInstrumentation implements TypeInstrumentation {
+    @Override
+    public ElementMatcher<TypeDescription> typeMatcher() {
+      // This is essentially the entry point of the AWS SDK, all clients implement it. We can ensure
+      // our interceptor service definition is injected as early as possible if we typematch against
+      // it.
+      return named("software.amazon.awssdk.core.SdkClient");
+    }
+
+    @Override
+    public void transform(TypeTransformer transformer) {
+      doTransform(transformer);
+    }
+  }
 }

+ 2 - 33
instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AwsSdkInstrumentationModule.java

@@ -5,19 +5,11 @@
 
 package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2;
 
-import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
-import static java.util.Collections.singletonList;
-import static net.bytebuddy.matcher.ElementMatchers.named;
-
 import com.google.auto.service.AutoService;
 import io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure.TracingExecutionInterceptor;
 import io.opentelemetry.javaagent.extension.instrumentation.HelperResourceBuilder;
 import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
-import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
-import java.util.List;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.matcher.ElementMatcher;
 
 @AutoService(InstrumentationModule.class)
 public class AwsSdkInstrumentationModule extends AbstractAwsSdkInstrumentationModule {
@@ -35,30 +27,7 @@ public class AwsSdkInstrumentationModule extends AbstractAwsSdkInstrumentationMo
   }
 
   @Override
-  public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
-    // We don't actually transform it but want to make sure we only apply the instrumentation when
-    // our key dependency is present.
-    return hasClassesNamed("software.amazon.awssdk.core.interceptor.ExecutionInterceptor");
-  }
-
-  @Override
-  public List<TypeInstrumentation> typeInstrumentations() {
-    return singletonList(new ResourceInjectingTypeInstrumentation());
-  }
-
-  // A type instrumentation is needed to trigger resource injection.
-  public static class ResourceInjectingTypeInstrumentation implements TypeInstrumentation {
-    @Override
-    public ElementMatcher<TypeDescription> typeMatcher() {
-      // This is essentially the entry point of the AWS SDK, all clients implement it. We can ensure
-      // our interceptor service definition is injected as early as possible if we typematch against
-      // it.
-      return named("software.amazon.awssdk.core.SdkClient");
-    }
-
-    @Override
-    public void transform(TypeTransformer transformer) {
-      // Nothing to transform, this type instrumentation is only used for injecting resources.
-    }
+  void doTransform(TypeTransformer transformer) {
+    // Nothing to transform, this type instrumentation is only used for injecting resources.
   }
 }

+ 5 - 23
instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/SqsInstrumentationModule.java

@@ -5,19 +5,13 @@
 
 package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2;
 
-import static java.util.Collections.singletonList;
-import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
-import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.none;
 
 import com.google.auto.service.AutoService;
 import io.opentelemetry.instrumentation.awssdk.v2_2.SqsAdviceBridge;
 import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
-import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
-import java.util.List;
 import net.bytebuddy.asm.Advice;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.matcher.ElementMatcher;
 
 @AutoService(InstrumentationModule.class)
 public class SqsInstrumentationModule extends AbstractAwsSdkInstrumentationModule {
@@ -27,21 +21,9 @@ public class SqsInstrumentationModule extends AbstractAwsSdkInstrumentationModul
   }
 
   @Override
-  public List<TypeInstrumentation> typeInstrumentations() {
-    return singletonList(new DefaultSqsClientTypeInstrumentation());
-  }
-
-  public static class DefaultSqsClientTypeInstrumentation implements TypeInstrumentation {
-    @Override
-    public ElementMatcher<TypeDescription> typeMatcher() {
-      return named("software.amazon.awssdk.services.sqs.DefaultSqsClient");
-    }
-
-    @Override
-    public void transform(TypeTransformer transformer) {
-      transformer.applyAdviceToMethod(
-          isConstructor(), SqsInstrumentationModule.class.getName() + "$RegisterAdvice");
-    }
+  public void doTransform(TypeTransformer transformer) {
+    transformer.applyAdviceToMethod(
+        none(), SqsInstrumentationModule.class.getName() + "$RegisterAdvice");
   }
 
   @SuppressWarnings("unused")
@@ -50,7 +32,7 @@ public class SqsInstrumentationModule extends AbstractAwsSdkInstrumentationModul
     public static void onExit() {
       // (indirectly) using SqsImpl class here to make sure it is available from SqsAccess
       // (injected into app classloader) and checked by Muzzle
-      SqsAdviceBridge.init();
+      SqsAdviceBridge.referenceForMuzzleOnly();
     }
   }
 }

+ 1 - 0
instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts

@@ -26,5 +26,6 @@ tasks {
   test {
     systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
     systemProperty("otel.instrumentation.aws-sdk.experimental-span-attributes", true)
+    systemProperty("otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", true)
   }
 }

+ 33 - 11
instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsAccess.java

@@ -8,12 +8,18 @@ package io.opentelemetry.instrumentation.awssdk.v2_2;
 import io.opentelemetry.context.propagation.TextMapPropagator;
 import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle;
 import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.SdkResponse;
 import software.amazon.awssdk.core.interceptor.Context;
 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse;
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
 
 // helper class for calling methods that use sqs types in SqsImpl
 // if SqsImpl is not present these methods are no op
 final class SqsAccess {
+  private SqsAccess() {}
+
   private static final boolean enabled = isSqsImplPresent();
 
   private static boolean isSqsImplPresent() {
@@ -31,14 +37,34 @@ final class SqsAccess {
   }
 
   @NoMuzzle
-  static SdkRequest injectIntoSqsSendMessageRequest(
+  static boolean isSendMessageRequest(SdkRequest request) {
+    return enabled && request instanceof SendMessageRequest;
+  }
+
+  @NoMuzzle
+  static SdkRequest injectIntoSendMessageRequest(
       TextMapPropagator messagingPropagator,
       SdkRequest rawRequest,
       io.opentelemetry.context.Context otelContext) {
-    if (!enabled) {
-      return rawRequest;
-    }
-    return SqsImpl.injectIntoSqsSendMessageRequest(messagingPropagator, rawRequest, otelContext);
+    assert enabled; // enabled checked already in instance check.
+    return SqsImpl.injectIntoSendMessageRequest(messagingPropagator, rawRequest, otelContext);
+  }
+
+  @NoMuzzle
+  static boolean isReceiveMessageRequest(SdkRequest request) {
+    return enabled && request instanceof ReceiveMessageRequest;
+  }
+
+  @NoMuzzle
+  public static SdkRequest modifyReceiveMessageRequest(
+      SdkRequest request, boolean useXrayPropagator, TextMapPropagator messagingPropagator) {
+    assert enabled; // enabled checked already in instance check.
+    return SqsImpl.modifyReceiveMessageRequest(request, useXrayPropagator, messagingPropagator);
+  }
+
+  @NoMuzzle
+  static boolean isReceiveMessageResponse(SdkResponse response) {
+    return enabled && response instanceof ReceiveMessageResponse;
   }
 
   @NoMuzzle
@@ -46,11 +72,7 @@ final class SqsAccess {
       TracingExecutionInterceptor config,
       Context.AfterExecution context,
       ExecutionAttributes executionAttributes) {
-    if (!enabled) {
-      return;
-    }
-    SqsImpl.afterConsumerResponse(config, executionAttributes, context);
+    assert enabled; // enabled checked already in instance check.
+    SqsImpl.afterReceiveMessageExecution(config, executionAttributes, context);
   }
-
-  private SqsAccess() {}
 }

+ 3 - 3
instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsAdviceBridge.java

@@ -8,8 +8,8 @@ package io.opentelemetry.instrumentation.awssdk.v2_2;
 public final class SqsAdviceBridge {
   private SqsAdviceBridge() {}
 
-  public static void init() {
-    // called from advice
-    SqsImpl.init(); // Reference the actual, package-private, implementation class for Muzzle
+  public static void referenceForMuzzleOnly() {
+    throw new UnsupportedOperationException(
+        SqsImpl.class.getName() + " referencing for muzzle, should never be actually called");
   }
 }

+ 45 - 6
instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsImpl.java

@@ -7,7 +7,9 @@ package io.opentelemetry.instrumentation.awssdk.v2_2;
 
 import io.opentelemetry.context.propagation.TextMapPropagator;
 import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import software.amazon.awssdk.core.SdkRequest;
 import software.amazon.awssdk.core.interceptor.Context;
@@ -15,6 +17,7 @@ import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
 import software.amazon.awssdk.http.SdkHttpResponse;
 import software.amazon.awssdk.services.sqs.model.Message;
 import software.amazon.awssdk.services.sqs.model.MessageAttributeValue;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
 import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse;
 import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
 
@@ -22,11 +25,7 @@ import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
 final class SqsImpl {
   private SqsImpl() {}
 
-  public static void init() {
-    // called from advice
-  }
-
-  static SdkRequest injectIntoSqsSendMessageRequest(
+  static SdkRequest injectIntoSendMessageRequest(
       TextMapPropagator messagingPropagator,
       SdkRequest rawRequest,
       io.opentelemetry.context.Context otelContext) {
@@ -48,7 +47,7 @@ final class SqsImpl {
   }
 
   /** Create and close CONSUMER span for each message consumed. */
-  static void afterConsumerResponse(
+  static void afterReceiveMessageExecution(
       TracingExecutionInterceptor config,
       ExecutionAttributes executionAttributes,
       Context.AfterExecution context) {
@@ -91,4 +90,44 @@ final class SqsImpl {
       consumerInstrumenter.end(context, executionAttributes, httpResponse, null);
     }
   }
+
+  static SdkRequest modifyReceiveMessageRequest(
+      SdkRequest rawRequest, boolean useXrayPropagator, TextMapPropagator messagingPropagator) {
+    ReceiveMessageRequest request = (ReceiveMessageRequest) rawRequest;
+    boolean hasXrayAttribute = true;
+    List<String> existingAttributeNames = null;
+    if (useXrayPropagator) {
+      existingAttributeNames = request.attributeNamesAsStrings();
+      hasXrayAttribute =
+          existingAttributeNames.contains(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE);
+    }
+
+    boolean hasMessageAttribute = true;
+    List<String> existingMessageAttributeNames = null;
+    if (messagingPropagator != null) {
+      existingMessageAttributeNames = request.messageAttributeNames();
+      hasMessageAttribute = existingMessageAttributeNames.containsAll(messagingPropagator.fields());
+    }
+
+    if (hasMessageAttribute && hasXrayAttribute) {
+      return request;
+    }
+
+    ReceiveMessageRequest.Builder builder = request.toBuilder();
+    if (!hasXrayAttribute) {
+      List<String> attributeNames = new ArrayList<>(existingAttributeNames);
+      attributeNames.add(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE);
+      builder.attributeNamesWithStrings(attributeNames);
+    }
+    if (messagingPropagator != null) {
+      List<String> messageAttributeNames = new ArrayList<>(existingMessageAttributeNames);
+      for (String field : messagingPropagator.fields()) {
+        if (!existingMessageAttributeNames.contains(field)) {
+          messageAttributeNames.add(field);
+        }
+      }
+      builder.messageAttributeNames(messageAttributeNames);
+    }
+    return builder.build();
+  }
 }

+ 0 - 122
instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsReceiveMessageRequestAccess.java

@@ -1,122 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v2_2;
-
-import static java.lang.invoke.MethodType.methodType;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import javax.annotation.Nullable;
-import software.amazon.awssdk.core.SdkRequest;
-
-/**
- * Reflective access to aws-sdk-java-sqs class ReceiveMessageRequest.
- *
- * <p>We currently don't have a good pattern of instrumenting a core library with various plugins
- * that need plugin-specific instrumentation - if we accessed the class directly, Muzzle would
- * prevent the entire instrumentation from loading when the plugin isn't available. We need to
- * carefully check this class has all reflection errors result in no-op, and in the future we will
- * hopefully come up with a better pattern.
- *
- * @see <a
- *     href="https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/ReceiveMessageRequest.html">SDK
- *     Javadoc</a>
- * @see <a
- *     href="https://github.com/aws/aws-sdk-java-v2/blob/2.2.0/services/sqs/src/main/resources/codegen-resources/service-2.json#L1076-L1110">Definition
- *     JSON</a>
- */
-final class SqsReceiveMessageRequestAccess {
-
-  @Nullable private static final MethodHandle ATTRIBUTE_NAMES_WITH_STRINGS;
-  @Nullable private static final MethodHandle MESSAGE_ATTRIBUTE_NAMES;
-
-  static {
-    Class<?> receiveMessageRequestClass = null;
-    try {
-      receiveMessageRequestClass =
-          Class.forName("software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest$Builder");
-    } catch (Throwable t) {
-      // Ignore.
-    }
-    if (receiveMessageRequestClass != null) {
-      MethodHandles.Lookup lookup = MethodHandles.publicLookup();
-      MethodHandle withAttributeNames = null;
-      try {
-        withAttributeNames =
-            lookup.findVirtual(
-                receiveMessageRequestClass,
-                "attributeNamesWithStrings",
-                methodType(receiveMessageRequestClass, Collection.class));
-      } catch (NoSuchMethodException | IllegalAccessException e) {
-        // Ignore
-      }
-      ATTRIBUTE_NAMES_WITH_STRINGS = withAttributeNames;
-
-      MethodHandle messageAttributeNames = null;
-      try {
-        messageAttributeNames =
-            lookup.findVirtual(
-                receiveMessageRequestClass,
-                "messageAttributeNames",
-                methodType(receiveMessageRequestClass, Collection.class));
-      } catch (NoSuchMethodException | IllegalAccessException e) {
-        // Ignore
-      }
-      MESSAGE_ATTRIBUTE_NAMES = messageAttributeNames;
-    } else {
-      ATTRIBUTE_NAMES_WITH_STRINGS = null;
-      MESSAGE_ATTRIBUTE_NAMES = null;
-    }
-  }
-
-  static boolean isInstance(SdkRequest request) {
-    return request
-        .getClass()
-        .getName()
-        .equals("software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest");
-  }
-
-  static void attributeNamesWithStrings(SdkRequest.Builder builder, List<String> attributeNames) {
-    if (ATTRIBUTE_NAMES_WITH_STRINGS == null) {
-      return;
-    }
-    try {
-      ATTRIBUTE_NAMES_WITH_STRINGS.invoke(builder, attributeNames);
-    } catch (Throwable throwable) {
-      // Ignore
-    }
-  }
-
-  static void messageAttributeNames(
-      SdkRequest.Builder builder, List<String> messageAttributeNames) {
-    if (MESSAGE_ATTRIBUTE_NAMES == null) {
-      return;
-    }
-    try {
-      MESSAGE_ATTRIBUTE_NAMES.invoke(builder, messageAttributeNames);
-    } catch (Throwable throwable) {
-      // Ignore
-    }
-  }
-
-  private SqsReceiveMessageRequestAccess() {}
-
-  @SuppressWarnings({"rawtypes", "unchecked"})
-  static List<String> getAttributeNames(SdkRequest request) {
-    Optional<List> optional = request.getValueForField("AttributeNames", List.class);
-    return optional.isPresent() ? (List<String>) optional.get() : Collections.emptyList();
-  }
-
-  @SuppressWarnings({"rawtypes", "unchecked"})
-  static List<String> getMessageAttributeNames(SdkRequest request) {
-    Optional<List> optional = request.getValueForField("MessageAttributeNames", List.class);
-    return optional.isPresent() ? (List<String>) optional.get() : Collections.emptyList();
-  }
-}

+ 0 - 23
instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/SqsSendMessageRequestAccess.java

@@ -1,23 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v2_2;
-
-import software.amazon.awssdk.core.SdkRequest;
-
-/**
- * Reflective access to aws-sdk-java-sqs class ReceiveMessageRequest for points where we are not
- * sure whether SQS is on the classpath.
- */
-final class SqsSendMessageRequestAccess {
-  static boolean isInstance(SdkRequest request) {
-    return request
-        .getClass()
-        .getName()
-        .equals("software.amazon.awssdk.services.sqs.model.SendMessageRequest");
-  }
-
-  private SqsSendMessageRequestAccess() {}
-}

+ 5 - 45
instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingExecutionInterceptor.java

@@ -15,7 +15,6 @@ import io.opentelemetry.context.propagation.TextMapPropagator;
 import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator;
 import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
 import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
-import java.util.ArrayList;
 import java.util.List;
 import javax.annotation.Nullable;
 import software.amazon.awssdk.awscore.AwsResponse;
@@ -122,56 +121,17 @@ final class TracingExecutionInterceptor implements ExecutionInterceptor {
       throw throwable;
     }
 
-    if (SqsReceiveMessageRequestAccess.isInstance(request)) {
-      return modifySqsReceiveMessageRequest(request);
+    if (SqsAccess.isReceiveMessageRequest(request)) {
+      return SqsAccess.modifyReceiveMessageRequest(request, useXrayPropagator, messagingPropagator);
     } else if (messagingPropagator != null) {
-      if (SqsSendMessageRequestAccess.isInstance(request)) {
-        return SqsAccess.injectIntoSqsSendMessageRequest(messagingPropagator, request, otelContext);
+      if (SqsAccess.isSendMessageRequest(request)) {
+        return SqsAccess.injectIntoSendMessageRequest(messagingPropagator, request, otelContext);
       }
       // TODO: Support SendMessageBatchRequest (and thus SendMessageBatchRequestEntry)
     }
     return request;
   }
 
-  private SdkRequest modifySqsReceiveMessageRequest(SdkRequest request) {
-    boolean hasXrayAttribute = true;
-    List<String> existingAttributeNames = null;
-    if (useXrayPropagator) {
-      existingAttributeNames = SqsReceiveMessageRequestAccess.getAttributeNames(request);
-      hasXrayAttribute =
-          existingAttributeNames.contains(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE);
-    }
-
-    boolean hasMessageAttribute = true;
-    List<String> existingMessageAttributeNames = null;
-    if (messagingPropagator != null) {
-      existingMessageAttributeNames =
-          SqsReceiveMessageRequestAccess.getMessageAttributeNames(request);
-      hasMessageAttribute = existingMessageAttributeNames.containsAll(messagingPropagator.fields());
-    }
-
-    if (hasMessageAttribute && hasXrayAttribute) {
-      return request;
-    }
-
-    SdkRequest.Builder builder = request.toBuilder();
-    if (!hasXrayAttribute) {
-      List<String> attributeNames = new ArrayList<>(existingAttributeNames);
-      attributeNames.add(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE);
-      SqsReceiveMessageRequestAccess.attributeNamesWithStrings(builder, attributeNames);
-    }
-    if (messagingPropagator != null) {
-      List<String> messageAttributeNames = new ArrayList<>(existingMessageAttributeNames);
-      for (String field : messagingPropagator.fields()) {
-        if (!existingMessageAttributeNames.contains(field)) {
-          messageAttributeNames.add(field);
-        }
-      }
-      SqsReceiveMessageRequestAccess.messageAttributeNames(builder, messageAttributeNames);
-    }
-    return builder.build();
-  }
-
   @Override
   public void afterMarshalling(
       Context.AfterMarshalling context, ExecutionAttributes executionAttributes) {
@@ -265,7 +225,7 @@ final class TracingExecutionInterceptor implements ExecutionInterceptor {
   @Override
   public void afterExecution(
       Context.AfterExecution context, ExecutionAttributes executionAttributes) {
-    if (SqsReceiveMessageRequestAccess.isInstance(context.request())) {
+    if (SqsAccess.isReceiveMessageResponse(context.response())) {
       SqsAccess.afterReceiveMessageExecution(this, context, executionAttributes);
     }
 

+ 1 - 1
instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/Aws2ClientTest.groovy

@@ -15,7 +15,7 @@ class Aws2ClientTest extends AbstractAws2ClientTest implements LibraryTestTrait
       .addExecutionInterceptor(
         AwsSdkTelemetry.builder(getOpenTelemetry())
           .setCaptureExperimentalSpanAttributes(true)
-          .setUseConfiguredPropagatorForMessaging(true) // Default on in tests to cover more code
+          .setUseConfiguredPropagatorForMessaging(isSqsAttributeInjectionEnabled())
           .build()
           .newExecutionInterceptor())
   }

+ 39 - 0
instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy

@@ -5,12 +5,14 @@
 
 package io.opentelemetry.instrumentation.awssdk.v2_2
 
+import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil
 import io.opentelemetry.instrumentation.test.InstrumentationSpecification
 import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
 import io.opentelemetry.testing.internal.armeria.common.HttpResponse
 import io.opentelemetry.testing.internal.armeria.common.HttpStatus
 import io.opentelemetry.testing.internal.armeria.common.MediaType
 import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension
+import org.junit.jupiter.api.Assumptions
 import software.amazon.awssdk.auth.credentials.AwsBasicCredentials
 import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider
 import software.amazon.awssdk.core.ResponseInputStream
@@ -48,6 +50,7 @@ import software.amazon.awssdk.services.s3.model.GetObjectRequest
 import software.amazon.awssdk.services.sqs.SqsAsyncClient
 import software.amazon.awssdk.services.sqs.SqsClient
 import software.amazon.awssdk.services.sqs.model.CreateQueueRequest
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest
 import spock.lang.Shared
 import spock.lang.Unroll
 
@@ -317,7 +320,22 @@ abstract class AbstractAws2ClientTest extends InstrumentationSpecification {
     return AttributeValue.builder().s(value).build()
   }
 
+  def isSqsAttributeInjectionEnabled() {
+    // See io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure.TracingExecutionInterceptor
+    return ConfigPropertiesUtil.getBoolean("otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", false)
+  }
+
+  void assumeSupportedConfig(service, operation) {
+    Assumptions.assumeFalse(
+        service == "Sqs"
+            && operation == "SendMessage"
+            && isSqsAttributeInjectionEnabled(),
+        "Cannot check Sqs.SendMessage here due to hard-coded MD5.")
+  }
+
   def "send #operation request with builder #builder.class.getName() mocked response"() {
+    assumeSupportedConfig(service, operation)
+
     setup:
     configureSdkClient(builder)
     def client = builder
@@ -384,6 +402,16 @@ abstract class AbstractAws2ClientTest extends InstrumentationSpecification {
             <ResponseMetadata><RequestId>7a62c49f-347e-4fc4-9331-6e8e7a96aa73</RequestId></ResponseMetadata>
         </CreateQueueResponse>
         """
+    "Sqs"     | "SendMessage"       | "POST" | ""                    | "27daac76-34dd-47df-bd01-1f6e873584a0" | SqsClient.builder()     | { c -> c.sendMessage(SendMessageRequest.builder().queueUrl("someurl").messageBody("").build()) } | """
+        <SendMessageResponse>
+            <SendMessageResult>
+                <MD5OfMessageBody>d41d8cd98f00b204e9800998ecf8427e</MD5OfMessageBody>
+                <MD5OfMessageAttributes>3ae8f24a165a8cedc005670c81a27295</MD5OfMessageAttributes>
+                <MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
+            </SendMessageResult>
+            <ResponseMetadata><RequestId>27daac76-34dd-47df-bd01-1f6e873584a0</RequestId></ResponseMetadata>
+        </SendMessageResponse>
+        """
     "Ec2"     | "AllocateAddress"   | "POST" | ""                    | "59dbff89-35bd-4eac-99ed-be587EXAMPLE" | Ec2Client.builder()     | { c -> c.allocateAddress() }                                                                     | """
         <AllocateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
            <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId> 
@@ -399,6 +427,7 @@ abstract class AbstractAws2ClientTest extends InstrumentationSpecification {
   }
 
   def "send #operation async request with builder #builder.class.getName() mocked response"() {
+    assumeSupportedConfig(service, operation)
     setup:
     configureSdkClient(builder)
     def client = builder
@@ -465,6 +494,16 @@ abstract class AbstractAws2ClientTest extends InstrumentationSpecification {
             <ResponseMetadata><RequestId>7a62c49f-347e-4fc4-9331-6e8e7a96aa73</RequestId></ResponseMetadata>
         </CreateQueueResponse>
         """
+    "Sqs"   | "SendMessage"       | "POST" | ""                            | "27daac76-34dd-47df-bd01-1f6e873584a0" | SqsAsyncClient.builder() | { c -> c.sendMessage(SendMessageRequest.builder().queueUrl("someurl").messageBody("").build()) }                                 | """
+        <SendMessageResponse>
+            <SendMessageResult>
+                <MD5OfMessageBody>d41d8cd98f00b204e9800998ecf8427e</MD5OfMessageBody>
+                <MD5OfMessageAttributes>3ae8f24a165a8cedc005670c81a27295</MD5OfMessageAttributes>
+                <MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
+            </SendMessageResult>
+            <ResponseMetadata><RequestId>27daac76-34dd-47df-bd01-1f6e873584a0</RequestId></ResponseMetadata>
+        </SendMessageResponse>
+        """
     "Ec2"   | "AllocateAddress"   | "POST" | ""                            | "59dbff89-35bd-4eac-99ed-be587EXAMPLE" | Ec2AsyncClient.builder() | { c -> c.allocateAddress() }                                                                                                     | """
         <AllocateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
            <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId> 

+ 7 - 6
instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2SqsTracingTest.groovy

@@ -6,7 +6,6 @@
 package io.opentelemetry.instrumentation.awssdk.v2_2
 
 import io.opentelemetry.instrumentation.test.InstrumentationSpecification
-import io.opentelemetry.instrumentation.test.utils.PortUtils
 import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
 import org.elasticmq.rest.sqs.SQSRestServerBuilder
 import software.amazon.awssdk.auth.credentials.AwsBasicCredentials
@@ -61,10 +60,10 @@ abstract class AbstractAws2SqsTracingTest extends InstrumentationSpecification {
   abstract ClientOverrideConfiguration.Builder createOverrideConfigurationBuilder()
 
   def setupSpec() {
-    sqsPort = PortUtils.findOpenPort()
-    sqs = SQSRestServerBuilder.withPort(sqsPort).withInterface("localhost").start()
+    sqs = SQSRestServerBuilder.withPort(0).withInterface("localhost").start()
+    def server = sqs.waitUntilStarted()
+    sqsPort = server.localAddress().port
     println getClass().name + " SQS server started at: localhost:$sqsPort/"
-
   }
 
   def cleanupSpec() {
@@ -181,9 +180,10 @@ abstract class AbstractAws2SqsTracingTest extends InstrumentationSpecification {
     when:
     client.sendMessage(sendMessageRequest)
 
-    client.receiveMessage(receiveMessageRequest)
+    def resp = client.receiveMessage(receiveMessageRequest)
 
     then:
+    resp.messages().size() == 1
     assertSqsTraces()
   }
 
@@ -198,9 +198,10 @@ abstract class AbstractAws2SqsTracingTest extends InstrumentationSpecification {
     when:
     client.sendMessage(sendMessageRequest).get()
 
-    client.receiveMessage(receiveMessageRequest).get()
+    def resp = client.receiveMessage(receiveMessageRequest).get()
 
     then:
+    resp.messages().size() == 1
     assertSqsTraces()
   }
 }

+ 2 - 0
instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java

@@ -12,6 +12,7 @@ import io.opentelemetry.api.logs.LogRecordBuilder;
 import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.ContextDataAccessor;
 import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.LogEventMapper;
 import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
+import java.time.Instant;
 import java.util.List;
 import java.util.Map;
 import java.util.function.BiConsumer;
@@ -66,6 +67,7 @@ public final class Log4jHelper {
             .logRecordBuilder();
     Map<String, String> contextData = ThreadContext.getImmutableContext();
     mapper.mapLogEvent(builder, message, level, marker, throwable, contextData);
+    builder.setTimestamp(Instant.now());
     builder.emit();
   }
 

+ 9 - 0
instrumentation/log4j/log4j-appender-2.17/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/Log4j2Test.java

@@ -8,6 +8,7 @@ package io.opentelemetry.instrumentation.log4j.appender.v2_17;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import io.opentelemetry.api.common.AttributeKey;
 import io.opentelemetry.api.logs.Severity;
@@ -16,6 +17,7 @@ import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
 import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
 import io.opentelemetry.sdk.logs.data.LogRecordData;
 import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+import java.time.Instant;
 import java.util.stream.Stream;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -68,6 +70,8 @@ class Log4j2Test {
       String expectedSeverityText)
       throws InterruptedException {
 
+    Instant start = Instant.now();
+
     // when
     if (withParent) {
       testing.runWithSpan(
@@ -88,6 +92,11 @@ class Log4j2Test {
           .hasInstrumentationScope(InstrumentationScopeInfo.builder(expectedLoggerName).build())
           .hasSeverity(expectedSeverity)
           .hasSeverityText(expectedSeverityText);
+
+      assertThat(log.getTimestampEpochNanos())
+          .isGreaterThanOrEqualTo(MILLISECONDS.toNanos(start.toEpochMilli()))
+          .isLessThanOrEqualTo(MILLISECONDS.toNanos(Instant.now().toEpochMilli()));
+
       if (logException) {
         assertThat(log)
             .hasAttributesSatisfyingExactly(

+ 3 - 3
instrumentation/log4j/log4j-appender-2.17/library/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppenderConfigTestBase.java

@@ -9,6 +9,7 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import io.opentelemetry.api.OpenTelemetry;
 import io.opentelemetry.api.common.Attributes;
@@ -24,7 +25,6 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider;
 import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
 import java.time.Instant;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.Marker;
@@ -107,8 +107,8 @@ abstract class OpenTelemetryAppenderConfigTestBase {
             satisfies(SemanticAttributes.EXCEPTION_STACKTRACE, v -> v.contains("logWithExtras")));
 
     assertThat(logDataList.get(0).getTimestampEpochNanos())
-        .isGreaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(start.toEpochMilli()))
-        .isLessThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli()));
+        .isGreaterThanOrEqualTo(MILLISECONDS.toNanos(start.toEpochMilli()))
+        .isLessThanOrEqualTo(MILLISECONDS.toNanos(Instant.now().toEpochMilli()));
   }
 
   @Test

+ 18 - 0
instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/BaseClusterInstrumentation.java

@@ -34,6 +34,14 @@ final class BaseClusterInstrumentation implements TypeInstrumentation {
             .and(takesArgument(0, named("com.mongodb.selector.ServerSelector")))
             .and(takesArgument(1, named("com.mongodb.internal.async.SingleResultCallback"))),
         this.getClass().getName() + "$SingleResultCallbackArg1Advice");
+
+    transformer.applyAdviceToMethod(
+        isMethod()
+            .and(isPublic())
+            .and(named("selectServerAsync"))
+            .and(takesArgument(0, named("com.mongodb.selector.ServerSelector")))
+            .and(takesArgument(2, named("com.mongodb.internal.async.SingleResultCallback"))),
+        this.getClass().getName() + "$SingleResultCallbackArg2Advice");
   }
 
   @SuppressWarnings("unused")
@@ -45,4 +53,14 @@ final class BaseClusterInstrumentation implements TypeInstrumentation {
       callback = new SingleResultCallbackWrapper(Java8BytecodeBridge.currentContext(), callback);
     }
   }
+
+  @SuppressWarnings("unused")
+  public static class SingleResultCallbackArg2Advice {
+
+    @Advice.OnMethodEnter(suppress = Throwable.class)
+    public static void wrapCallback(
+        @Advice.Argument(value = 2, readOnly = false) SingleResultCallback<Object> callback) {
+      callback = new SingleResultCallbackWrapper(Java8BytecodeBridge.currentContext(), callback);
+    }
+  }
 }

+ 43 - 0
instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/DefaultConnectionPoolTaskInstrumentation.java

@@ -0,0 +1,43 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.mongo.v4_0;
+
+import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
+
+import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
+import java.util.function.Consumer;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+public class DefaultConnectionPoolTaskInstrumentation implements TypeInstrumentation {
+  @Override
+  public ElementMatcher<TypeDescription> typeMatcher() {
+    return named("com.mongodb.internal.connection.DefaultConnectionPool$Task");
+  }
+
+  @Override
+  public void transform(TypeTransformer transformer) {
+    // outer class this is passed as arg 0 to constructor
+    transformer.applyAdviceToMethod(
+        isConstructor().and(takesArgument(2, Consumer.class)),
+        this.getClass().getName() + "$TaskAdvice");
+  }
+
+  @SuppressWarnings("unused")
+  public static class TaskAdvice {
+
+    @Advice.OnMethodEnter(suppress = Throwable.class)
+    public static void wrapCallback(
+        @Advice.Argument(value = 2, readOnly = false) Consumer<Object> action) {
+      action = new TaskWrapper(Java8BytecodeBridge.currentContext(), action);
+    }
+  }
+}

+ 1 - 0
instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/MongoClientInstrumentationModule.java

@@ -33,6 +33,7 @@ public class MongoClientInstrumentationModule extends InstrumentationModule {
         new InternalStreamConnectionInstrumentation(),
         new BaseClusterInstrumentation(),
         new DefaultConnectionPoolInstrumentation(),
+        new DefaultConnectionPoolTaskInstrumentation(),
         new AsyncWorkManagerInstrumentation());
   }
 }

+ 27 - 0
instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/TaskWrapper.java

@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.mongo.v4_0;
+
+import io.opentelemetry.context.Context;
+import io.opentelemetry.context.Scope;
+import java.util.function.Consumer;
+
+public class TaskWrapper implements Consumer<Object> {
+  private final Context context;
+  private final Consumer<Object> delegate;
+
+  public TaskWrapper(Context context, Consumer<Object> delegate) {
+    this.context = context;
+    this.delegate = delegate;
+  }
+
+  @Override
+  public void accept(Object value) {
+    try (Scope ignored = context.makeCurrent()) {
+      delegate.accept(value);
+    }
+  }
+}

+ 0 - 2
instrumentation/resources/library/src/test/resources/docker_proc_self_mountinfo

@@ -1,5 +1,3 @@
-473 456 254:1 /docker/containers/be522444b60caf2d3934b8b24b916a8a314f4b68d4595aa419874657e8d103f2/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw
-root@be522444b60c:/# cat /proc/self/mountinfo
 456 375 0:143 / / rw,relatime master:175 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/CBPR2ETR4Z3UMOOGIIRDVT2P27:/var/lib/docker/overlay2/l/46FCA2JFPCSNFGAR5TSYLLNHLK,upperdir=/var/lib/docker/overlay2/3ef3e5a1a87b4e220c1da9a7901654e945b0ef5398e1b67fccb42fdb7750829e/diff,workdir=/var/lib/docker/overlay2/3ef3e5a1a87b4e220c1da9a7901654e945b0ef5398e1b67fccb42fdb7750829e/work
 457 456 0:146 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
 466 456 0:147 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755

+ 0 - 2
instrumentation/resources/library/src/test/resources/podman_proc_self_mountinfo

@@ -1,5 +1,3 @@
-983 961 0:56 /containers/overlay-containers/2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6/userdata/hostname /etc/hostname ro,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=783888k,nr_inodes=195972,mode=700,uid=2024,gid=2024,inode64
-[root@2a33efc76e51 /]# cat /proc/self/mountinfo
 961 812 0:58 / / ro,relatime - overlay overlay rw,lowerdir=/home/dracula/.local/share/containers/storage/overlay/l/4NB35A5Z4YGWDHXYEUZU4FN6BU,upperdir=/home/dracula/.local/share/containers/storage/overlay/a73044caca1b918335d1db6f0052d21d35045136f3aa86976dbad1ec96e2fdde/diff,workdir=/home/dracula/.local/share/containers/storage/overlay/a73044caca1b918335d1db6f0052d21d35045136f3aa86976dbad1ec96e2fdde/work,userxattr
 962 961 0:63 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs rw
 963 961 0:64 / /run rw,nosuid,nodev,relatime - tmpfs tmpfs rw,uid=2024,gid=2024,inode64

+ 1 - 1
settings.gradle.kts

@@ -14,7 +14,7 @@ pluginManagement {
 }
 
 plugins {
-  id("com.gradle.enterprise") version "3.13.3"
+  id("com.gradle.enterprise") version "3.13.4"
   id("com.gradle.common-custom-user-data-gradle-plugin") version "1.11"
   id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
 }

+ 1 - 1
smoke-tests/images/fake-backend/build.gradle.kts

@@ -12,7 +12,7 @@ plugins {
 }
 
 dependencies {
-  implementation("com.linecorp.armeria:armeria-grpc:1.24.0")
+  implementation("com.linecorp.armeria:armeria-grpc:1.24.1")
   implementation("io.opentelemetry.proto:opentelemetry-proto")
   runtimeOnly("org.slf4j:slf4j-simple")
 }

+ 1 - 1
testing/armeria-shaded-for-testing/build.gradle.kts

@@ -5,7 +5,7 @@ plugins {
 }
 
 dependencies {
-  implementation("com.linecorp.armeria:armeria-junit5:1.24.0")
+  implementation("com.linecorp.armeria:armeria-junit5:1.24.1")
 }
 
 tasks {