Skip to content

refactor(fastapi): replace uses of SpanAttributes with opentelemetry.semconv.attributes #3491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
from opentelemetry.instrumentation.fastapi.version import __version__
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.metrics import get_meter
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE
from opentelemetry.trace import get_tracer
from opentelemetry.util.http import (
get_excluded_urls,
Expand Down Expand Up @@ -450,7 +450,7 @@ def _get_default_span_details(scope):
if method == "_OTHER":
method = "HTTP"
if route:
attributes[SpanAttributes.HTTP_ROUTE] = route
attributes[HTTP_ROUTE] = route
if method and route: # http
span_name = f"{method} {route}"
elif route: # websocket
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@
NumberDataPoint,
)
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv._incubating.attributes.http_attributes import (
HTTP_FLAVOR,
HTTP_HOST,
HTTP_METHOD,
HTTP_SCHEME,
HTTP_SERVER_NAME,
HTTP_STATUS_CODE,
HTTP_TARGET,
HTTP_URL,
)
from opentelemetry.semconv._incubating.attributes.net_attributes import NET_HOST_PORT
from opentelemetry.semconv.attributes.http_attributes import (
HTTP_REQUEST_METHOD,
HTTP_RESPONSE_STATUS_CODE,
Expand All @@ -55,7 +66,6 @@
NETWORK_PROTOCOL_VERSION,
)
from opentelemetry.semconv.attributes.url_attributes import URL_SCHEME
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.test.globals_test import reset_trace_globals
from opentelemetry.test.test_base import TestBase
from opentelemetry.util._importlib_metadata import entry_points
Expand Down Expand Up @@ -85,15 +95,15 @@
"http.server.active_requests": _server_active_requests_count_attrs_old,
"http.server.duration": {
*_server_duration_attrs_old,
SpanAttributes.HTTP_TARGET,
HTTP_TARGET,
},
"http.server.response.size": {
*_server_duration_attrs_old,
SpanAttributes.HTTP_TARGET,
HTTP_TARGET,
},
"http.server.request.size": {
*_server_duration_attrs_old,
SpanAttributes.HTTP_TARGET,
HTTP_TARGET,
},
}

Expand Down Expand Up @@ -245,8 +255,8 @@ def test_sub_app_fastapi_call(self):
span
for span in spans
if (
SpanAttributes.HTTP_URL in span.attributes
or SpanAttributes.HTTP_TARGET in span.attributes
HTTP_URL in span.attributes
or HTTP_TARGET in span.attributes
)
]

Expand All @@ -256,11 +266,11 @@ def test_sub_app_fastapi_call(self):

for span in spans_with_http_attributes:
self.assertEqual(
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
"/sub/home", span.attributes[HTTP_TARGET]
)
self.assertEqual(
"https://testserver:443/sub/home",
span.attributes[SpanAttributes.HTTP_URL],
span.attributes[HTTP_URL],
)


Expand Down Expand Up @@ -309,8 +319,8 @@ def test_sub_app_fastapi_call(self):
span
for span in spans
if (
SpanAttributes.HTTP_URL in span.attributes
or SpanAttributes.HTTP_TARGET in span.attributes
HTTP_URL in span.attributes
or HTTP_TARGET in span.attributes
)
]

Expand All @@ -319,11 +329,11 @@ def test_sub_app_fastapi_call(self):

for span in spans_with_http_attributes:
self.assertEqual(
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
"/sub/home", span.attributes[HTTP_TARGET]
)
self.assertEqual(
"https://testserver:443/sub/home",
span.attributes[SpanAttributes.HTTP_URL],
span.attributes[HTTP_URL],
)


Expand Down Expand Up @@ -382,12 +392,12 @@ def test_fastapi_route_attribute_added(self):
for span in spans:
self.assertIn("GET /user/{username}", span.name)
self.assertEqual(
spans[-1].attributes[SpanAttributes.HTTP_ROUTE], "/user/{username}"
spans[-1].attributes[HTTP_ROUTE], "/user/{username}"
)
# ensure that at least one attribute that is populated by
# the asgi instrumentation is successfully feeding though.
self.assertEqual(
spans[-1].attributes[SpanAttributes.HTTP_FLAVOR], "1.1"
spans[-1].attributes[HTTP_FLAVOR], "1.1"
)

def test_fastapi_excluded_urls(self):
Expand Down Expand Up @@ -511,21 +521,21 @@ def test_basic_metric_success(self):
self._client.get("/foobar")
duration = max(round((default_timer() - start) * 1000), 0)
expected_duration_attributes = {
SpanAttributes.HTTP_METHOD: "GET",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
SpanAttributes.NET_HOST_PORT: 443,
SpanAttributes.HTTP_STATUS_CODE: 200,
SpanAttributes.HTTP_TARGET: "/foobar",
HTTP_METHOD: "GET",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
NET_HOST_PORT: 443,
HTTP_STATUS_CODE: 200,
HTTP_TARGET: "/foobar",
}
expected_requests_count_attributes = {
SpanAttributes.HTTP_METHOD: "GET",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
HTTP_METHOD: "GET",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
}
metrics_list = self.memory_metrics_reader.get_metrics_data()
for metric in (
Expand Down Expand Up @@ -593,14 +603,14 @@ def test_basic_metric_success_both_semconv(self):
duration = max(round((default_timer() - start) * 1000), 0)
duration_s = max(default_timer() - start, 0)
expected_duration_attributes_old = {
SpanAttributes.HTTP_METHOD: "GET",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
SpanAttributes.NET_HOST_PORT: 443,
SpanAttributes.HTTP_STATUS_CODE: 200,
SpanAttributes.HTTP_TARGET: "/foobar",
HTTP_METHOD: "GET",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
NET_HOST_PORT: 443,
HTTP_STATUS_CODE: 200,
HTTP_TARGET: "/foobar",
}
expected_duration_attributes_new = {
HTTP_REQUEST_METHOD: "GET",
Expand All @@ -610,11 +620,11 @@ def test_basic_metric_success_both_semconv(self):
HTTP_ROUTE: "/foobar",
}
expected_requests_count_attributes = {
SpanAttributes.HTTP_METHOD: "GET",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
HTTP_METHOD: "GET",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
HTTP_REQUEST_METHOD: "GET",
URL_SCHEME: "https",
}
Expand Down Expand Up @@ -676,21 +686,21 @@ def test_basic_metric_nonstandard_http_method_success(self):
self._client.request("NONSTANDARD", "/foobar")
duration = max(round((default_timer() - start) * 1000), 0)
expected_duration_attributes = {
SpanAttributes.HTTP_METHOD: "_OTHER",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
SpanAttributes.NET_HOST_PORT: 443,
SpanAttributes.HTTP_STATUS_CODE: 405,
SpanAttributes.HTTP_TARGET: "/foobar",
HTTP_METHOD: "_OTHER",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
NET_HOST_PORT: 443,
HTTP_STATUS_CODE: 405,
HTTP_TARGET: "/foobar",
}
expected_requests_count_attributes = {
SpanAttributes.HTTP_METHOD: "_OTHER",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
HTTP_METHOD: "_OTHER",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
}
metrics_list = self.memory_metrics_reader.get_metrics_data()
for metric in (
Expand Down Expand Up @@ -758,14 +768,14 @@ def test_basic_metric_nonstandard_http_method_success_both_semconv(self):
duration = max(round((default_timer() - start) * 1000), 0)
duration_s = max(default_timer() - start, 0)
expected_duration_attributes_old = {
SpanAttributes.HTTP_METHOD: "_OTHER",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
SpanAttributes.NET_HOST_PORT: 443,
SpanAttributes.HTTP_STATUS_CODE: 405,
SpanAttributes.HTTP_TARGET: "/foobar",
HTTP_METHOD: "_OTHER",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
NET_HOST_PORT: 443,
HTTP_STATUS_CODE: 405,
HTTP_TARGET: "/foobar",
}
expected_duration_attributes_new = {
HTTP_REQUEST_METHOD: "_OTHER",
Expand All @@ -775,11 +785,11 @@ def test_basic_metric_nonstandard_http_method_success_both_semconv(self):
HTTP_ROUTE: "/foobar",
}
expected_requests_count_attributes = {
SpanAttributes.HTTP_METHOD: "_OTHER",
SpanAttributes.HTTP_HOST: "testserver:443",
SpanAttributes.HTTP_SCHEME: "https",
SpanAttributes.HTTP_FLAVOR: "1.1",
SpanAttributes.HTTP_SERVER_NAME: "testserver",
HTTP_METHOD: "_OTHER",
HTTP_HOST: "testserver:443",
HTTP_SCHEME: "https",
HTTP_FLAVOR: "1.1",
HTTP_SERVER_NAME: "testserver",
HTTP_REQUEST_METHOD: "_OTHER",
URL_SCHEME: "https",
}
Expand Down Expand Up @@ -1204,8 +1214,8 @@ def test_sub_app_fastapi_call(self):
span
for span in spans
if (
SpanAttributes.HTTP_URL in span.attributes
or SpanAttributes.HTTP_TARGET in span.attributes
HTTP_URL in span.attributes
or HTTP_TARGET in span.attributes
)
]

Expand All @@ -1214,11 +1224,11 @@ def test_sub_app_fastapi_call(self):

for span in spans_with_http_attributes:
self.assertEqual(
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
"/sub/home", span.attributes[HTTP_TARGET]
)
self.assertEqual(
"https://testserver:443/sub/home",
span.attributes[SpanAttributes.HTTP_URL],
span.attributes[HTTP_URL],
)


Expand Down Expand Up @@ -1297,8 +1307,8 @@ def test_sub_app_fastapi_call(self):
span
for span in spans
if (
SpanAttributes.HTTP_URL in span.attributes
or SpanAttributes.HTTP_TARGET in span.attributes
HTTP_URL in span.attributes
or HTTP_TARGET in span.attributes
)
]

Expand All @@ -1307,11 +1317,11 @@ def test_sub_app_fastapi_call(self):

for span in spans_with_http_attributes:
self.assertEqual(
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
"/sub/home", span.attributes[HTTP_TARGET]
)
self.assertEqual(
"https://testserver:443/sub/home",
span.attributes[SpanAttributes.HTTP_URL],
span.attributes[HTTP_URL],
)


Expand Down