Repository: open-telemetry/opentelemetry-python-contrib

Issue:
Fix asgi instrumentation default span name
Similar to [wsgi](https://github.com/open-telemetry/opentelemetry-python/blob/master/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py#L171), the default span name for SERVER spans should be `HTTP <method>` as outlined by the [specs](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#name).

Part of https://github.com/open-telemetry/opentelemetry-python-contrib/issues/434


Discussion:
This issue was marked stale due to lack of activity. It will be closed in 30 days.

Resolving patch:
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py
--- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py
@@ -146,12 +146,13 @@ def get_default_span_details(scope: dict) -> Tuple[str, dict]:
         scope: the asgi scope dictionary
 
     Returns:
-        a tuple of the span, and any attributes to attach to the
-        span.
+        a tuple of the span name, and any attributes to attach to the span.
     """
-    method_or_path = scope.get("method") or scope.get("path")
+    span_name = scope.get("path", "").strip() or "HTTP {}".format(
+        scope.get("method", "").strip()
+    )
 
-    return method_or_path, {}
+    return span_name, {}
 
 
 class OpenTelemetryMiddleware:
@@ -204,7 +205,7 @@ async def __call__(self, scope, receive, send):
 
         try:
             with self.tracer.start_as_current_span(
-                span_name + " asgi", kind=trace.SpanKind.SERVER,
+                span_name, kind=trace.SpanKind.SERVER,
             ) as span:
                 if span.is_recording():
                     attributes = collect_request_attributes(scope)
@@ -215,7 +216,7 @@ async def __call__(self, scope, receive, send):
                 @wraps(receive)
                 async def wrapped_receive():
                     with self.tracer.start_as_current_span(
-                        span_name + " asgi." + scope["type"] + ".receive"
+                        " ".join((span_name, scope["type"], "receive"))
                     ) as receive_span:
                         message = await receive()
                         if receive_span.is_recording():
@@ -227,7 +228,7 @@ async def wrapped_receive():
                 @wraps(send)
                 async def wrapped_send(message):
                     with self.tracer.start_as_current_span(
-                        span_name + " asgi." + scope["type"] + ".send"
+                        " ".join((span_name, scope["type"], "send"))
                     ) as send_span:
                         if send_span.is_recording():
                             if message["type"] == "http.response.start":


Test patch:
diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py
--- a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py
+++ b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py
@@ -116,12 +116,12 @@ def validate_outputs(self, outputs, error=None, modifiers=None):
         self.assertEqual(len(span_list), 4)
         expected = [
             {
-                "name": "GET asgi.http.receive",
+                "name": "/ http receive",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {"type": "http.request"},
             },
             {
-                "name": "GET asgi.http.send",
+                "name": "/ http send",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {
                     SpanAttributes.HTTP_STATUS_CODE: 200,
@@ -129,12 +129,12 @@ def validate_outputs(self, outputs, error=None, modifiers=None):
                 },
             },
             {
-                "name": "GET asgi.http.send",
+                "name": "/ http send",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {"type": "http.response.body"},
             },
             {
-                "name": "GET asgi",
+                "name": "/",
                 "kind": trace_api.SpanKind.SERVER,
                 "attributes": {
                     SpanAttributes.HTTP_METHOD: "GET",
@@ -201,9 +201,12 @@ def get_predefined_span_details(_):
 
         def update_expected_span_name(expected):
             for entry in expected:
-                entry["name"] = " ".join(
-                    [span_name] + entry["name"].split(" ")[-1:]
-                )
+                if entry["kind"] == trace_api.SpanKind.SERVER:
+                    entry["name"] = span_name
+                else:
+                    entry["name"] = " ".join(
+                        [span_name] + entry["name"].split(" ")[1:]
+                    )
             return expected
 
         app = otel_asgi.OpenTelemetryMiddleware(
@@ -305,17 +308,17 @@ def test_websocket(self):
         self.assertEqual(len(span_list), 6)
         expected = [
             {
-                "name": "/ asgi.websocket.receive",
+                "name": "/ websocket receive",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {"type": "websocket.connect"},
             },
             {
-                "name": "/ asgi.websocket.send",
+                "name": "/ websocket send",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {"type": "websocket.accept"},
             },
             {
-                "name": "/ asgi.websocket.receive",
+                "name": "/ websocket receive",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {
                     "type": "websocket.receive",
@@ -323,7 +326,7 @@ def test_websocket(self):
                 },
             },
             {
-                "name": "/ asgi.websocket.send",
+                "name": "/ websocket send",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {
                     "type": "websocket.send",
@@ -331,12 +334,12 @@ def test_websocket(self):
                 },
             },
             {
-                "name": "/ asgi.websocket.receive",
+                "name": "/ websocket receive",
                 "kind": trace_api.SpanKind.INTERNAL,
                 "attributes": {"type": "websocket.disconnect"},
             },
             {
-                "name": "/ asgi",
+                "name": "/",
                 "kind": trace_api.SpanKind.SERVER,
                 "attributes": {
                     SpanAttributes.HTTP_SCHEME: self.scope["scheme"],