Browse Source

Change `network.protocol.name` from opt-in to conditionally required (#9797)

Mateusz Rzeszutek 1 year ago
parent
commit
dbe90c5fcf
18 changed files with 107 additions and 31 deletions
  1. 1 0
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractor.java
  2. 2 1
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorBuilder.java
  3. 23 0
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpCommonAttributesExtractor.java
  4. 1 0
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java
  5. 2 2
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorBuilder.java
  6. 1 1
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/net/NetClientAttributesExtractor.java
  7. 1 1
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/net/NetServerAttributesExtractor.java
  8. 1 1
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/network/NetworkAttributesExtractor.java
  9. 9 11
      instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/network/internal/InternalNetworkAttributesExtractor.java
  10. 0 1
      instrumentation-api-semconv/src/testBothHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorBothSemconvTest.java
  11. 0 1
      instrumentation-api-semconv/src/testBothHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorBothSemconvTest.java
  12. 25 1
      instrumentation-api-semconv/src/testStableHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorStableSemconvTest.java
  13. 25 1
      instrumentation-api-semconv/src/testStableHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorStableSemconvTest.java
  14. 7 5
      instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionTest.java
  15. 0 2
      instrumentation/undertow-1.4/javaagent/src/test/groovy/UndertowServerTest.groovy
  16. 5 1
      testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpClientTest.java
  17. 4 1
      testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java
  18. 0 1
      testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpClientTestOptions.java

+ 1 - 0
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractor.java

@@ -91,6 +91,7 @@ public final class HttpClientAttributesExtractor<REQUEST, RESPONSE>
   HttpClientAttributesExtractor(HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> builder) {
     super(
         builder.httpAttributesGetter,
+        builder.netAttributesGetter,
         HttpStatusCodeConverter.CLIENT,
         builder.capturedRequestHeaders,
         builder.capturedResponseHeaders,

+ 2 - 1
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorBuilder.java

@@ -136,7 +136,8 @@ public final class HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> {
     return new InternalNetworkAttributesExtractor<>(
         netAttributesGetter,
         serverAddressAndPortExtractor,
-        /* captureNetworkTransportAndType= */ false,
+        // network.{transport,type} are opt-in, network.protocol.* have HTTP-specific logic
+        /* captureProtocolAttributes= */ false,
         /* captureLocalSocketAttributes= */ false,
         /* captureOldPeerDomainAttribute= */ true,
         SemconvStability.emitStableHttpSemconv(),

+ 23 - 0
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpCommonAttributesExtractor.java

@@ -17,10 +17,12 @@ import io.opentelemetry.api.common.AttributesBuilder;
 import io.opentelemetry.context.Context;
 import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
 import io.opentelemetry.instrumentation.api.instrumenter.http.internal.HttpAttributes;
+import io.opentelemetry.instrumentation.api.instrumenter.network.NetworkAttributesGetter;
 import io.opentelemetry.instrumentation.api.internal.SemconvStability;
 import io.opentelemetry.semconv.SemanticAttributes;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import javax.annotation.Nullable;
 
@@ -34,6 +36,7 @@ abstract class HttpCommonAttributesExtractor<
     implements AttributesExtractor<REQUEST, RESPONSE> {
 
   final GETTER getter;
+  final NetworkAttributesGetter<REQUEST, RESPONSE> networkGetter;
   private final HttpStatusCodeConverter statusCodeConverter;
   private final List<String> capturedRequestHeaders;
   private final List<String> capturedResponseHeaders;
@@ -41,11 +44,13 @@ abstract class HttpCommonAttributesExtractor<
 
   HttpCommonAttributesExtractor(
       GETTER getter,
+      NetworkAttributesGetter<REQUEST, RESPONSE> networkGetter,
       HttpStatusCodeConverter statusCodeConverter,
       List<String> capturedRequestHeaders,
       List<String> capturedResponseHeaders,
       Set<String> knownMethods) {
     this.getter = getter;
+    this.networkGetter = networkGetter;
     this.statusCodeConverter = statusCodeConverter;
     this.capturedRequestHeaders = lowercase(capturedRequestHeaders);
     this.capturedResponseHeaders = lowercase(capturedResponseHeaders);
@@ -143,6 +148,19 @@ abstract class HttpCommonAttributesExtractor<
       }
       internalSet(attributes, HttpAttributes.ERROR_TYPE, errorType);
     }
+
+    if (SemconvStability.emitStableHttpSemconv()) {
+      String protocolName = lowercaseStr(networkGetter.getNetworkProtocolName(request, response));
+      String protocolVersion =
+          lowercaseStr(networkGetter.getNetworkProtocolVersion(request, response));
+
+      if (protocolVersion != null) {
+        if (!"http".equals(protocolName)) {
+          internalSet(attributes, SemanticAttributes.NETWORK_PROTOCOL_NAME, protocolName);
+        }
+        internalSet(attributes, SemanticAttributes.NETWORK_PROTOCOL_VERSION, protocolVersion);
+      }
+    }
   }
 
   @Nullable
@@ -173,4 +191,9 @@ abstract class HttpCommonAttributesExtractor<
       return null;
     }
   }
+
+  @Nullable
+  private static String lowercaseStr(@Nullable String str) {
+    return str == null ? null : str.toLowerCase(Locale.ROOT);
+  }
 }

+ 1 - 0
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java

@@ -93,6 +93,7 @@ public final class HttpServerAttributesExtractor<REQUEST, RESPONSE>
   HttpServerAttributesExtractor(HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> builder) {
     super(
         builder.httpAttributesGetter,
+        builder.netAttributesGetter,
         HttpStatusCodeConverter.SERVER,
         builder.capturedRequestHeaders,
         builder.capturedResponseHeaders,

+ 2 - 2
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorBuilder.java

@@ -149,8 +149,8 @@ public final class HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> {
     return new InternalNetworkAttributesExtractor<>(
         netAttributesGetter,
         clientAddressPortExtractor,
-        // network.type and network.transport are opt-in
-        /* captureNetworkTransportAndType= */ false,
+        // network.{transport,type} are opt-in, network.protocol.* have HTTP-specific logic
+        /* captureProtocolAttributes= */ false,
         // network.local.* are opt-in
         /* captureLocalSocketAttributes= */ false,
         /* captureOldPeerDomainAttribute= */ false,

+ 1 - 1
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/net/NetClientAttributesExtractor.java

@@ -51,7 +51,7 @@ public final class NetClientAttributesExtractor<REQUEST, RESPONSE>
         new InternalNetworkAttributesExtractor<>(
             getter,
             serverAddressAndPortExtractor,
-            /* captureNetworkTransportAndType= */ true,
+            /* captureProtocolAttributes= */ true,
             /* captureLocalSocketAttributes= */ false,
             /* captureOldPeerDomainAttribute= */ true,
             SemconvStability.emitStableHttpSemconv(),

+ 1 - 1
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/net/NetServerAttributesExtractor.java

@@ -53,7 +53,7 @@ public final class NetServerAttributesExtractor<REQUEST, RESPONSE>
         new InternalNetworkAttributesExtractor<>(
             getter,
             clientAddressAndPortExtractor,
-            /* captureNetworkTransportAndType= */ true,
+            /* captureProtocolAttributes= */ true,
             /* captureLocalSocketAttributes= */ true,
             /* captureOldPeerDomainAttribute= */ false,
             SemconvStability.emitStableHttpSemconv(),

+ 1 - 1
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/network/NetworkAttributesExtractor.java

@@ -37,7 +37,7 @@ public final class NetworkAttributesExtractor<REQUEST, RESPONSE>
         new InternalNetworkAttributesExtractor<>(
             getter,
             AddressAndPortExtractor.noop(),
-            /* captureNetworkTransportAndType= */ true,
+            /* captureProtocolAttributes= */ true,
             /* captureLocalSocketAttributes= */ true,
             // capture the old net.sock.peer.name attr for backwards compatibility
             /* captureOldPeerDomainAttribute= */ true,

+ 9 - 11
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/network/internal/InternalNetworkAttributesExtractor.java

@@ -23,7 +23,7 @@ public final class InternalNetworkAttributesExtractor<REQUEST, RESPONSE> {
 
   private final NetworkAttributesGetter<REQUEST, RESPONSE> getter;
   private final AddressAndPortExtractor<REQUEST> logicalPeerAddressAndPortExtractor;
-  private final boolean captureNetworkTransportAndType;
+  private final boolean captureProtocolAttributes;
   private final boolean captureLocalSocketAttributes;
   private final boolean captureOldPeerDomainAttribute;
   private final boolean emitStableUrlAttributes;
@@ -32,14 +32,14 @@ public final class InternalNetworkAttributesExtractor<REQUEST, RESPONSE> {
   public InternalNetworkAttributesExtractor(
       NetworkAttributesGetter<REQUEST, RESPONSE> getter,
       AddressAndPortExtractor<REQUEST> logicalPeerAddressAndPortExtractor,
-      boolean captureNetworkTransportAndType,
+      boolean captureProtocolAttributes,
       boolean captureLocalSocketAttributes,
       boolean captureOldPeerDomainAttribute,
       boolean emitStableUrlAttributes,
       boolean emitOldHttpAttributes) {
     this.getter = getter;
     this.logicalPeerAddressAndPortExtractor = logicalPeerAddressAndPortExtractor;
-    this.captureNetworkTransportAndType = captureNetworkTransportAndType;
+    this.captureProtocolAttributes = captureProtocolAttributes;
     this.captureLocalSocketAttributes = captureLocalSocketAttributes;
     this.captureOldPeerDomainAttribute = captureOldPeerDomainAttribute;
     this.emitStableUrlAttributes = emitStableUrlAttributes;
@@ -51,15 +51,13 @@ public final class InternalNetworkAttributesExtractor<REQUEST, RESPONSE> {
     String protocolName = lowercase(getter.getNetworkProtocolName(request, response));
     String protocolVersion = lowercase(getter.getNetworkProtocolVersion(request, response));
 
-    if (emitStableUrlAttributes) {
+    if (emitStableUrlAttributes && captureProtocolAttributes) {
       String transport = lowercase(getter.getNetworkTransport(request, response));
-      if (captureNetworkTransportAndType) {
-        internalSet(attributes, SemanticAttributes.NETWORK_TRANSPORT, transport);
-        internalSet(
-            attributes,
-            SemanticAttributes.NETWORK_TYPE,
-            lowercase(getter.getNetworkType(request, response)));
-      }
+      internalSet(attributes, SemanticAttributes.NETWORK_TRANSPORT, transport);
+      internalSet(
+          attributes,
+          SemanticAttributes.NETWORK_TYPE,
+          lowercase(getter.getNetworkType(request, response)));
       internalSet(attributes, SemanticAttributes.NETWORK_PROTOCOL_NAME, protocolName);
       internalSet(attributes, SemanticAttributes.NETWORK_PROTOCOL_VERSION, protocolVersion);
     }

+ 0 - 1
instrumentation-api-semconv/src/testBothHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorBothSemconvTest.java

@@ -167,7 +167,6 @@ class HttpClientAttributesExtractorBothSemconvTest {
                 asList("654", "321")),
             entry(SemanticAttributes.NET_PROTOCOL_NAME, "http"),
             entry(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1"),
-            entry(SemanticAttributes.NETWORK_PROTOCOL_NAME, "http"),
             entry(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1"));
   }
 }

+ 0 - 1
instrumentation-api-semconv/src/testBothHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorBothSemconvTest.java

@@ -169,7 +169,6 @@ class HttpServerAttributesExtractorBothSemconvTest {
         .containsOnly(
             entry(SemanticAttributes.NET_PROTOCOL_NAME, "http"),
             entry(SemanticAttributes.NET_PROTOCOL_VERSION, "2.0"),
-            entry(SemanticAttributes.NETWORK_PROTOCOL_NAME, "http"),
             entry(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "2.0"),
             entry(SemanticAttributes.HTTP_ROUTE, "/repositories/{repoId}"),
             entry(SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH, 10L),

+ 25 - 1
instrumentation-api-semconv/src/testStableHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorStableSemconvTest.java

@@ -186,7 +186,6 @@ class HttpClientAttributesExtractorStableSemconvTest {
             entry(
                 AttributeKey.stringArrayKey("http.response.header.custom-response-header"),
                 asList("654", "321")),
-            entry(SemanticAttributes.NETWORK_PROTOCOL_NAME, "http"),
             entry(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
             entry(NetworkAttributes.NETWORK_PEER_ADDRESS, "4.3.2.1"),
             entry(NetworkAttributes.NETWORK_PEER_PORT, 456L));
@@ -397,4 +396,29 @@ class HttpClientAttributesExtractorStableSemconvTest {
             entry(NetworkAttributes.NETWORK_PEER_ADDRESS, "1.2.3.4"),
             entry(NetworkAttributes.NETWORK_PEER_PORT, 456L));
   }
+
+  @Test
+  void shouldExtractProtocolNameDifferentFromHttp() {
+    Map<String, String> request = new HashMap<>();
+    request.put("networkProtocolName", "spdy");
+    request.put("networkProtocolVersion", "3.1");
+
+    Map<String, String> response = new HashMap<>();
+    response.put("statusCode", "200");
+
+    AttributesExtractor<Map<String, String>, Map<String, String>> extractor =
+        HttpClientAttributesExtractor.create(new TestHttpClientAttributesGetter());
+
+    AttributesBuilder startAttributes = Attributes.builder();
+    extractor.onStart(startAttributes, Context.root(), request);
+    assertThat(startAttributes.build()).isEmpty();
+
+    AttributesBuilder endAttributes = Attributes.builder();
+    extractor.onEnd(endAttributes, Context.root(), request, response, null);
+    assertThat(endAttributes.build())
+        .containsOnly(
+            entry(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200L),
+            entry(SemanticAttributes.NETWORK_PROTOCOL_NAME, "spdy"),
+            entry(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "3.1"));
+  }
 }

+ 25 - 1
instrumentation-api-semconv/src/testStableHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorStableSemconvTest.java

@@ -211,7 +211,6 @@ class HttpServerAttributesExtractorStableSemconvTest {
     extractor.onEnd(endAttributes, Context.root(), request, response, null);
     assertThat(endAttributes.build())
         .containsOnly(
-            entry(SemanticAttributes.NETWORK_PROTOCOL_NAME, "http"),
             entry(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "2.0"),
             entry(NetworkAttributes.NETWORK_PEER_ADDRESS, "4.3.2.1"),
             entry(NetworkAttributes.NETWORK_PEER_PORT, 456L),
@@ -528,4 +527,29 @@ class HttpServerAttributesExtractorStableSemconvTest {
             entry(NetworkAttributes.NETWORK_PEER_ADDRESS, "1.2.3.4"),
             entry(NetworkAttributes.NETWORK_PEER_PORT, 456L));
   }
+
+  @Test
+  void shouldExtractProtocolNameDifferentFromHttp() {
+    Map<String, String> request = new HashMap<>();
+    request.put("networkProtocolName", "spdy");
+    request.put("networkProtocolVersion", "3.1");
+
+    Map<String, String> response = new HashMap<>();
+    response.put("statusCode", "200");
+
+    AttributesExtractor<Map<String, String>, Map<String, String>> extractor =
+        HttpServerAttributesExtractor.create(new TestHttpServerAttributesGetter());
+
+    AttributesBuilder startAttributes = Attributes.builder();
+    extractor.onStart(startAttributes, Context.root(), request);
+    assertThat(startAttributes.build()).isEmpty();
+
+    AttributesBuilder endAttributes = Attributes.builder();
+    extractor.onEnd(endAttributes, Context.root(), request, response, null);
+    assertThat(endAttributes.build())
+        .containsOnly(
+            entry(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200L),
+            entry(SemanticAttributes.NETWORK_PROTOCOL_NAME, "spdy"),
+            entry(SemanticAttributes.NETWORK_PROTOCOL_VERSION, "3.1"));
+  }
 }

+ 7 - 5
instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionTest.java

@@ -124,7 +124,6 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
     List<AttributeAssertion> attributes =
         new ArrayList<>(
             Arrays.asList(
-                equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME), "http"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_VERSION), "1.1"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_NAME), "localhost"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_PORT), url.getPort()),
@@ -132,6 +131,7 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_METHOD), "GET"),
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_STATUS_CODE), STATUS)));
     if (SemconvStability.emitOldHttpSemconv()) {
+      attributes.add(equalTo(SemanticAttributes.NET_PROTOCOL_NAME, "http"));
       attributes.add(
           satisfies(
               SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, AbstractLongAssert::isNotNegative));
@@ -176,7 +176,6 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
     List<AttributeAssertion> attributes =
         new ArrayList<>(
             Arrays.asList(
-                equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME), "http"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_VERSION), "1.1"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_NAME), "localhost"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_PORT), url.getPort()),
@@ -184,6 +183,7 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_METHOD), "GET"),
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_STATUS_CODE), STATUS)));
     if (SemconvStability.emitOldHttpSemconv()) {
+      attributes.add(equalTo(SemanticAttributes.NET_PROTOCOL_NAME, "http"));
       attributes.add(
           satisfies(
               SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, AbstractLongAssert::isNotNegative));
@@ -234,7 +234,6 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
     List<AttributeAssertion> attributes =
         new ArrayList<>(
             Arrays.asList(
-                equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME), "http"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_VERSION), "1.1"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_NAME), "localhost"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_PORT), url.getPort()),
@@ -242,6 +241,7 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_METHOD), "POST"),
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_STATUS_CODE), STATUS)));
     if (SemconvStability.emitOldHttpSemconv()) {
+      attributes.add(equalTo(SemanticAttributes.NET_PROTOCOL_NAME, "http"));
       attributes.add(
           satisfies(
               SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH, AbstractLongAssert::isNotNegative));
@@ -297,7 +297,6 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
     List<AttributeAssertion> attributes =
         new ArrayList<>(
             Arrays.asList(
-                equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME), "http"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_VERSION), "1.1"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_NAME), "localhost"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_PORT), url.getPort()),
@@ -305,6 +304,7 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_METHOD), "POST"),
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_STATUS_CODE), STATUS)));
     if (SemconvStability.emitOldHttpSemconv()) {
+      attributes.add(equalTo(SemanticAttributes.NET_PROTOCOL_NAME, "http"));
       attributes.add(
           satisfies(
               SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH, AbstractLongAssert::isNotNegative));
@@ -349,12 +349,14 @@ class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
     List<AttributeAssertion> attributes =
         new ArrayList<>(
             Arrays.asList(
-                equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME), "http"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PROTOCOL_VERSION), "1.1"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_NAME), "localhost"),
                 equalTo(getAttributeKey(SemanticAttributes.NET_PEER_PORT), PortUtils.UNUSABLE_PORT),
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_URL), uri),
                 equalTo(getAttributeKey(SemanticAttributes.HTTP_METHOD), "GET")));
+    if (SemconvStability.emitOldHttpSemconv()) {
+      attributes.add(equalTo(SemanticAttributes.NET_PROTOCOL_NAME, "http"));
+    }
     if (SemconvStability.emitStableHttpSemconv()) {
       attributes.add(equalTo(HttpAttributes.ERROR_TYPE, "java.net.ConnectException"));
     }

+ 0 - 2
instrumentation/undertow-1.4/javaagent/src/test/groovy/UndertowServerTest.groovy

@@ -171,7 +171,6 @@ class UndertowServerTest extends HttpServerTest<Undertow> implements AgentTestTr
               "$SemanticAttributes.HTTP_REQUEST_METHOD" "GET"
               "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200
               "$SemanticAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT
-              "$SemanticAttributes.NETWORK_PROTOCOL_NAME" "http"
               "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
               "$SemanticAttributes.SERVER_ADDRESS" uri.host
               "$SemanticAttributes.SERVER_PORT" uri.port
@@ -242,7 +241,6 @@ class UndertowServerTest extends HttpServerTest<Undertow> implements AgentTestTr
               "$SemanticAttributes.HTTP_REQUEST_METHOD" "GET"
               "$SemanticAttributes.HTTP_RESPONSE_STATUS_CODE" 200
               "$SemanticAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT
-              "$SemanticAttributes.NETWORK_PROTOCOL_NAME" "http"
               "$SemanticAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
               "$SemanticAttributes.SERVER_ADDRESS" uri.host
               "$SemanticAttributes.SERVER_PORT" uri.port

+ 5 - 1
testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpClientTest.java

@@ -1024,9 +1024,13 @@ public abstract class AbstractHttpClientTest<REQUEST> implements HttpClientTypeA
                     .doesNotContainKey(SemanticAttributes.NETWORK_TRANSPORT)
                     .doesNotContainKey(SemanticAttributes.NETWORK_TYPE);
               }
+
               AttributeKey<String> netProtocolKey =
                   getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME);
-              if (httpClientAttributes.contains(netProtocolKey)) {
+              if (SemconvStability.emitStableHttpSemconv()) {
+                // only protocol names different from "http" are emitted
+                assertThat(attrs).doesNotContainKey(netProtocolKey);
+              } else if (attrs.get(netProtocolKey) != null) {
                 assertThat(attrs).containsEntry(netProtocolKey, "http");
               }
               AttributeKey<String> netProtocolVersionKey =

+ 4 - 1
testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java

@@ -798,7 +798,10 @@ public abstract class AbstractHttpServerTest<SERVER> extends AbstractHttpServerU
 
           AttributeKey<String> netProtocolKey =
               getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME);
-          if (attrs.get(netProtocolKey) != null) {
+          if (SemconvStability.emitStableHttpSemconv()) {
+            // only protocol names different from "http" are emitted
+            assertThat(attrs).doesNotContainKey(netProtocolKey);
+          } else if (attrs.get(netProtocolKey) != null) {
             assertThat(attrs).containsEntry(netProtocolKey, "http");
           }
           AttributeKey<String> netProtocolVersionKey =

+ 0 - 1
testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpClientTestOptions.java

@@ -28,7 +28,6 @@ public abstract class HttpClientTestOptions {
       Collections.unmodifiableSet(
           new HashSet<>(
               Arrays.asList(
-                  SemconvStabilityUtil.getAttributeKey(SemanticAttributes.NET_PROTOCOL_NAME),
                   SemconvStabilityUtil.getAttributeKey(SemanticAttributes.NET_PROTOCOL_VERSION),
                   SemconvStabilityUtil.getAttributeKey(SemanticAttributes.NET_PEER_NAME),
                   SemconvStabilityUtil.getAttributeKey(SemanticAttributes.NET_PEER_PORT),