Skip to content

Commit ec73158

Browse files
TheShubhendraxrmx
andauthored
refactor(fastapi): replace uses of SpanAttributes with opentelemetry.semconv.attributes (#3491)
* refactor(fastapi): migrate HTTP_ROUTE from SpanAttributes to new semantic conventions Replaced usage of `SpanAttributes.HTTP_ROUTE` with `opentelemetry.semconv.attributes.http_attributes.HTTP_ROUTE` as part of the migration away from `SpanAttributes`. Refs: #3475 * refactor(fastapi): refactor tests * refactor(fastapi): remove duplicated import * sort imports --------- Co-authored-by: Riccardo Magliocchetti <[email protected]>
1 parent ccdf522 commit ec73158

File tree

2 files changed

+86
-76
lines changed

2 files changed

+86
-76
lines changed

instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
204204
from opentelemetry.instrumentation.fastapi.version import __version__
205205
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
206206
from opentelemetry.metrics import get_meter
207-
from opentelemetry.semconv.trace import SpanAttributes
207+
from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE
208208
from opentelemetry.trace import get_tracer
209209
from opentelemetry.util.http import (
210210
get_excluded_urls,
@@ -450,7 +450,7 @@ def _get_default_span_details(scope):
450450
if method == "_OTHER":
451451
method = "HTTP"
452452
if route:
453-
attributes[SpanAttributes.HTTP_ROUTE] = route
453+
attributes[HTTP_ROUTE] = route
454454
if method and route: # http
455455
span_name = f"{method} {route}"
456456
elif route: # websocket

instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py

Lines changed: 84 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@
4646
NumberDataPoint,
4747
)
4848
from opentelemetry.sdk.resources import Resource
49+
from opentelemetry.semconv._incubating.attributes.http_attributes import (
50+
HTTP_FLAVOR,
51+
HTTP_HOST,
52+
HTTP_METHOD,
53+
HTTP_SCHEME,
54+
HTTP_SERVER_NAME,
55+
HTTP_STATUS_CODE,
56+
HTTP_TARGET,
57+
HTTP_URL,
58+
)
59+
from opentelemetry.semconv._incubating.attributes.net_attributes import NET_HOST_PORT
4960
from opentelemetry.semconv.attributes.http_attributes import (
5061
HTTP_REQUEST_METHOD,
5162
HTTP_RESPONSE_STATUS_CODE,
@@ -55,7 +66,6 @@
5566
NETWORK_PROTOCOL_VERSION,
5667
)
5768
from opentelemetry.semconv.attributes.url_attributes import URL_SCHEME
58-
from opentelemetry.semconv.trace import SpanAttributes
5969
from opentelemetry.test.globals_test import reset_trace_globals
6070
from opentelemetry.test.test_base import TestBase
6171
from opentelemetry.util._importlib_metadata import entry_points
@@ -85,15 +95,15 @@
8595
"http.server.active_requests": _server_active_requests_count_attrs_old,
8696
"http.server.duration": {
8797
*_server_duration_attrs_old,
88-
SpanAttributes.HTTP_TARGET,
98+
HTTP_TARGET,
8999
},
90100
"http.server.response.size": {
91101
*_server_duration_attrs_old,
92-
SpanAttributes.HTTP_TARGET,
102+
HTTP_TARGET,
93103
},
94104
"http.server.request.size": {
95105
*_server_duration_attrs_old,
96-
SpanAttributes.HTTP_TARGET,
106+
HTTP_TARGET,
97107
},
98108
}
99109

@@ -245,8 +255,8 @@ def test_sub_app_fastapi_call(self):
245255
span
246256
for span in spans
247257
if (
248-
SpanAttributes.HTTP_URL in span.attributes
249-
or SpanAttributes.HTTP_TARGET in span.attributes
258+
HTTP_URL in span.attributes
259+
or HTTP_TARGET in span.attributes
250260
)
251261
]
252262

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

257267
for span in spans_with_http_attributes:
258268
self.assertEqual(
259-
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
269+
"/sub/home", span.attributes[HTTP_TARGET]
260270
)
261271
self.assertEqual(
262272
"https://testserver:443/sub/home",
263-
span.attributes[SpanAttributes.HTTP_URL],
273+
span.attributes[HTTP_URL],
264274
)
265275

266276

@@ -309,8 +319,8 @@ def test_sub_app_fastapi_call(self):
309319
span
310320
for span in spans
311321
if (
312-
SpanAttributes.HTTP_URL in span.attributes
313-
or SpanAttributes.HTTP_TARGET in span.attributes
322+
HTTP_URL in span.attributes
323+
or HTTP_TARGET in span.attributes
314324
)
315325
]
316326

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

320330
for span in spans_with_http_attributes:
321331
self.assertEqual(
322-
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
332+
"/sub/home", span.attributes[HTTP_TARGET]
323333
)
324334
self.assertEqual(
325335
"https://testserver:443/sub/home",
326-
span.attributes[SpanAttributes.HTTP_URL],
336+
span.attributes[HTTP_URL],
327337
)
328338

329339

@@ -382,12 +392,12 @@ def test_fastapi_route_attribute_added(self):
382392
for span in spans:
383393
self.assertIn("GET /user/{username}", span.name)
384394
self.assertEqual(
385-
spans[-1].attributes[SpanAttributes.HTTP_ROUTE], "/user/{username}"
395+
spans[-1].attributes[HTTP_ROUTE], "/user/{username}"
386396
)
387397
# ensure that at least one attribute that is populated by
388398
# the asgi instrumentation is successfully feeding though.
389399
self.assertEqual(
390-
spans[-1].attributes[SpanAttributes.HTTP_FLAVOR], "1.1"
400+
spans[-1].attributes[HTTP_FLAVOR], "1.1"
391401
)
392402

393403
def test_fastapi_excluded_urls(self):
@@ -511,21 +521,21 @@ def test_basic_metric_success(self):
511521
self._client.get("/foobar")
512522
duration = max(round((default_timer() - start) * 1000), 0)
513523
expected_duration_attributes = {
514-
SpanAttributes.HTTP_METHOD: "GET",
515-
SpanAttributes.HTTP_HOST: "testserver:443",
516-
SpanAttributes.HTTP_SCHEME: "https",
517-
SpanAttributes.HTTP_FLAVOR: "1.1",
518-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
519-
SpanAttributes.NET_HOST_PORT: 443,
520-
SpanAttributes.HTTP_STATUS_CODE: 200,
521-
SpanAttributes.HTTP_TARGET: "/foobar",
524+
HTTP_METHOD: "GET",
525+
HTTP_HOST: "testserver:443",
526+
HTTP_SCHEME: "https",
527+
HTTP_FLAVOR: "1.1",
528+
HTTP_SERVER_NAME: "testserver",
529+
NET_HOST_PORT: 443,
530+
HTTP_STATUS_CODE: 200,
531+
HTTP_TARGET: "/foobar",
522532
}
523533
expected_requests_count_attributes = {
524-
SpanAttributes.HTTP_METHOD: "GET",
525-
SpanAttributes.HTTP_HOST: "testserver:443",
526-
SpanAttributes.HTTP_SCHEME: "https",
527-
SpanAttributes.HTTP_FLAVOR: "1.1",
528-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
534+
HTTP_METHOD: "GET",
535+
HTTP_HOST: "testserver:443",
536+
HTTP_SCHEME: "https",
537+
HTTP_FLAVOR: "1.1",
538+
HTTP_SERVER_NAME: "testserver",
529539
}
530540
metrics_list = self.memory_metrics_reader.get_metrics_data()
531541
for metric in (
@@ -593,14 +603,14 @@ def test_basic_metric_success_both_semconv(self):
593603
duration = max(round((default_timer() - start) * 1000), 0)
594604
duration_s = max(default_timer() - start, 0)
595605
expected_duration_attributes_old = {
596-
SpanAttributes.HTTP_METHOD: "GET",
597-
SpanAttributes.HTTP_HOST: "testserver:443",
598-
SpanAttributes.HTTP_SCHEME: "https",
599-
SpanAttributes.HTTP_FLAVOR: "1.1",
600-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
601-
SpanAttributes.NET_HOST_PORT: 443,
602-
SpanAttributes.HTTP_STATUS_CODE: 200,
603-
SpanAttributes.HTTP_TARGET: "/foobar",
606+
HTTP_METHOD: "GET",
607+
HTTP_HOST: "testserver:443",
608+
HTTP_SCHEME: "https",
609+
HTTP_FLAVOR: "1.1",
610+
HTTP_SERVER_NAME: "testserver",
611+
NET_HOST_PORT: 443,
612+
HTTP_STATUS_CODE: 200,
613+
HTTP_TARGET: "/foobar",
604614
}
605615
expected_duration_attributes_new = {
606616
HTTP_REQUEST_METHOD: "GET",
@@ -610,11 +620,11 @@ def test_basic_metric_success_both_semconv(self):
610620
HTTP_ROUTE: "/foobar",
611621
}
612622
expected_requests_count_attributes = {
613-
SpanAttributes.HTTP_METHOD: "GET",
614-
SpanAttributes.HTTP_HOST: "testserver:443",
615-
SpanAttributes.HTTP_SCHEME: "https",
616-
SpanAttributes.HTTP_FLAVOR: "1.1",
617-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
623+
HTTP_METHOD: "GET",
624+
HTTP_HOST: "testserver:443",
625+
HTTP_SCHEME: "https",
626+
HTTP_FLAVOR: "1.1",
627+
HTTP_SERVER_NAME: "testserver",
618628
HTTP_REQUEST_METHOD: "GET",
619629
URL_SCHEME: "https",
620630
}
@@ -676,21 +686,21 @@ def test_basic_metric_nonstandard_http_method_success(self):
676686
self._client.request("NONSTANDARD", "/foobar")
677687
duration = max(round((default_timer() - start) * 1000), 0)
678688
expected_duration_attributes = {
679-
SpanAttributes.HTTP_METHOD: "_OTHER",
680-
SpanAttributes.HTTP_HOST: "testserver:443",
681-
SpanAttributes.HTTP_SCHEME: "https",
682-
SpanAttributes.HTTP_FLAVOR: "1.1",
683-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
684-
SpanAttributes.NET_HOST_PORT: 443,
685-
SpanAttributes.HTTP_STATUS_CODE: 405,
686-
SpanAttributes.HTTP_TARGET: "/foobar",
689+
HTTP_METHOD: "_OTHER",
690+
HTTP_HOST: "testserver:443",
691+
HTTP_SCHEME: "https",
692+
HTTP_FLAVOR: "1.1",
693+
HTTP_SERVER_NAME: "testserver",
694+
NET_HOST_PORT: 443,
695+
HTTP_STATUS_CODE: 405,
696+
HTTP_TARGET: "/foobar",
687697
}
688698
expected_requests_count_attributes = {
689-
SpanAttributes.HTTP_METHOD: "_OTHER",
690-
SpanAttributes.HTTP_HOST: "testserver:443",
691-
SpanAttributes.HTTP_SCHEME: "https",
692-
SpanAttributes.HTTP_FLAVOR: "1.1",
693-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
699+
HTTP_METHOD: "_OTHER",
700+
HTTP_HOST: "testserver:443",
701+
HTTP_SCHEME: "https",
702+
HTTP_FLAVOR: "1.1",
703+
HTTP_SERVER_NAME: "testserver",
694704
}
695705
metrics_list = self.memory_metrics_reader.get_metrics_data()
696706
for metric in (
@@ -758,14 +768,14 @@ def test_basic_metric_nonstandard_http_method_success_both_semconv(self):
758768
duration = max(round((default_timer() - start) * 1000), 0)
759769
duration_s = max(default_timer() - start, 0)
760770
expected_duration_attributes_old = {
761-
SpanAttributes.HTTP_METHOD: "_OTHER",
762-
SpanAttributes.HTTP_HOST: "testserver:443",
763-
SpanAttributes.HTTP_SCHEME: "https",
764-
SpanAttributes.HTTP_FLAVOR: "1.1",
765-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
766-
SpanAttributes.NET_HOST_PORT: 443,
767-
SpanAttributes.HTTP_STATUS_CODE: 405,
768-
SpanAttributes.HTTP_TARGET: "/foobar",
771+
HTTP_METHOD: "_OTHER",
772+
HTTP_HOST: "testserver:443",
773+
HTTP_SCHEME: "https",
774+
HTTP_FLAVOR: "1.1",
775+
HTTP_SERVER_NAME: "testserver",
776+
NET_HOST_PORT: 443,
777+
HTTP_STATUS_CODE: 405,
778+
HTTP_TARGET: "/foobar",
769779
}
770780
expected_duration_attributes_new = {
771781
HTTP_REQUEST_METHOD: "_OTHER",
@@ -775,11 +785,11 @@ def test_basic_metric_nonstandard_http_method_success_both_semconv(self):
775785
HTTP_ROUTE: "/foobar",
776786
}
777787
expected_requests_count_attributes = {
778-
SpanAttributes.HTTP_METHOD: "_OTHER",
779-
SpanAttributes.HTTP_HOST: "testserver:443",
780-
SpanAttributes.HTTP_SCHEME: "https",
781-
SpanAttributes.HTTP_FLAVOR: "1.1",
782-
SpanAttributes.HTTP_SERVER_NAME: "testserver",
788+
HTTP_METHOD: "_OTHER",
789+
HTTP_HOST: "testserver:443",
790+
HTTP_SCHEME: "https",
791+
HTTP_FLAVOR: "1.1",
792+
HTTP_SERVER_NAME: "testserver",
783793
HTTP_REQUEST_METHOD: "_OTHER",
784794
URL_SCHEME: "https",
785795
}
@@ -1204,8 +1214,8 @@ def test_sub_app_fastapi_call(self):
12041214
span
12051215
for span in spans
12061216
if (
1207-
SpanAttributes.HTTP_URL in span.attributes
1208-
or SpanAttributes.HTTP_TARGET in span.attributes
1217+
HTTP_URL in span.attributes
1218+
or HTTP_TARGET in span.attributes
12091219
)
12101220
]
12111221

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

12151225
for span in spans_with_http_attributes:
12161226
self.assertEqual(
1217-
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
1227+
"/sub/home", span.attributes[HTTP_TARGET]
12181228
)
12191229
self.assertEqual(
12201230
"https://testserver:443/sub/home",
1221-
span.attributes[SpanAttributes.HTTP_URL],
1231+
span.attributes[HTTP_URL],
12221232
)
12231233

12241234

@@ -1297,8 +1307,8 @@ def test_sub_app_fastapi_call(self):
12971307
span
12981308
for span in spans
12991309
if (
1300-
SpanAttributes.HTTP_URL in span.attributes
1301-
or SpanAttributes.HTTP_TARGET in span.attributes
1310+
HTTP_URL in span.attributes
1311+
or HTTP_TARGET in span.attributes
13021312
)
13031313
]
13041314

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

13081318
for span in spans_with_http_attributes:
13091319
self.assertEqual(
1310-
"/sub/home", span.attributes[SpanAttributes.HTTP_TARGET]
1320+
"/sub/home", span.attributes[HTTP_TARGET]
13111321
)
13121322
self.assertEqual(
13131323
"https://testserver:443/sub/home",
1314-
span.attributes[SpanAttributes.HTTP_URL],
1324+
span.attributes[HTTP_URL],
13151325
)
13161326

13171327

0 commit comments

Comments
 (0)