Skip to content

Commit bb7865d

Browse files
fix(httpx): Set code.namespace and code.function instead of code.function.name in span streaming (#6150)
Set separate attributes because `co_qualname` requires Python 3.11+, so the fully-qualified name required by `code.function.name` is not available. The behavior now mirrors that for non-streamed spans.
1 parent 12efdd5 commit bb7865d

2 files changed

Lines changed: 31 additions & 13 deletions

File tree

sentry_sdk/tracing_utils.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,11 @@ def add_source(
283283
namespace = frame.f_globals.get("__name__")
284284
except Exception:
285285
namespace = None
286-
if namespace is not None and isinstance(span, LegacySpan):
287-
span.set_data(SPANDATA.CODE_NAMESPACE, namespace)
286+
if namespace is not None:
287+
if isinstance(span, LegacySpan):
288+
span.set_data(SPANDATA.CODE_NAMESPACE, namespace)
289+
else:
290+
span.set_attribute(SPANDATA.CODE_NAMESPACE, namespace)
288291

289292
filepath = _get_frame_module_abs_path(frame)
290293
if filepath is not None:
@@ -310,7 +313,7 @@ def add_source(
310313
if isinstance(span, LegacySpan):
311314
span.set_data(SPANDATA.CODE_FUNCTION, frame.f_code.co_name)
312315
else:
313-
span.set_attribute("code.function.name", frame.f_code.co_name)
316+
span.set_attribute(SPANDATA.CODE_FUNCTION, frame.f_code.co_name)
314317

315318

316319
def add_query_source(span: "sentry_sdk.tracing.Span") -> None:

tests/integrations/httpx/test_httpx.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -830,8 +830,9 @@ def test_request_source_disabled_span_streaming(
830830
http_span = _get_http_client_span(items)
831831

832832
assert "code.line.number" not in http_span["attributes"]
833+
assert SPANDATA.CODE_NAMESPACE not in http_span["attributes"]
833834
assert "code.file.path" not in http_span["attributes"]
834-
assert "code.function.name" not in http_span["attributes"]
835+
assert SPANDATA.CODE_FUNCTION not in http_span["attributes"]
835836

836837

837838
@pytest.mark.parametrize("enable_http_request_source", [None, True])
@@ -873,8 +874,9 @@ def test_request_source_enabled_span_streaming(
873874
http_span = _get_http_client_span(items)
874875

875876
assert "code.line.number" in http_span["attributes"]
877+
assert SPANDATA.CODE_NAMESPACE in http_span["attributes"]
876878
assert "code.file.path" in http_span["attributes"]
877-
assert "code.function.name" in http_span["attributes"]
879+
assert SPANDATA.CODE_FUNCTION in http_span["attributes"]
878880

879881

880882
@pytest.mark.parametrize(
@@ -908,11 +910,16 @@ def test_request_source_span_streaming(
908910
http_span = _get_http_client_span(items)
909911

910912
assert "code.line.number" in http_span["attributes"]
913+
assert SPANDATA.CODE_NAMESPACE in http_span["attributes"]
911914
assert "code.file.path" in http_span["attributes"]
912-
assert "code.function.name" in http_span["attributes"]
915+
assert SPANDATA.CODE_FUNCTION in http_span["attributes"]
913916

914917
assert type(http_span["attributes"]["code.line.number"]) == int
915918
assert http_span["attributes"]["code.line.number"] > 0
919+
assert (
920+
http_span["attributes"][SPANDATA.CODE_NAMESPACE]
921+
== "tests.integrations.httpx.test_httpx"
922+
)
916923
assert http_span["attributes"]["code.file.path"].endswith(
917924
"tests/integrations/httpx/test_httpx.py"
918925
)
@@ -921,7 +928,7 @@ def test_request_source_span_streaming(
921928
assert is_relative_path
922929

923930
assert (
924-
http_span["attributes"]["code.function.name"]
931+
http_span["attributes"][SPANDATA.CODE_FUNCTION]
925932
== "test_request_source_span_streaming"
926933
)
927934

@@ -966,24 +973,26 @@ def test_request_source_with_module_in_search_path_span_streaming(
966973
http_span = _get_http_client_span(items)
967974

968975
assert "code.line.number" in http_span["attributes"]
976+
assert SPANDATA.CODE_NAMESPACE in http_span["attributes"]
969977
assert "code.file.path" in http_span["attributes"]
970-
assert "code.function.name" in http_span["attributes"]
978+
assert SPANDATA.CODE_FUNCTION in http_span["attributes"]
971979

972980
assert type(http_span["attributes"]["code.line.number"]) == int
973981
assert http_span["attributes"]["code.line.number"] > 0
982+
assert http_span["attributes"][SPANDATA.CODE_NAMESPACE] == "httpx_helpers.helpers"
974983
assert http_span["attributes"]["code.file.path"] == "httpx_helpers/helpers.py"
975984

976985
is_relative_path = http_span["attributes"]["code.file.path"][0] != os.sep
977986
assert is_relative_path
978987

979988
if asyncio.iscoroutinefunction(httpx_client.get):
980989
assert (
981-
http_span["attributes"]["code.function.name"]
990+
http_span["attributes"][SPANDATA.CODE_FUNCTION]
982991
== "async_get_request_with_client"
983992
)
984993
else:
985994
assert (
986-
http_span["attributes"]["code.function.name"] == "get_request_with_client"
995+
http_span["attributes"][SPANDATA.CODE_FUNCTION] == "get_request_with_client"
987996
)
988997

989998

@@ -1019,8 +1028,9 @@ def test_no_request_source_if_duration_too_short_span_streaming(
10191028
http_span = _get_http_client_span(items)
10201029

10211030
assert "code.line.number" not in http_span["attributes"]
1031+
assert SPANDATA.CODE_NAMESPACE not in http_span["attributes"]
10221032
assert "code.file.path" not in http_span["attributes"]
1023-
assert "code.function.name" not in http_span["attributes"]
1033+
assert SPANDATA.CODE_FUNCTION not in http_span["attributes"]
10241034

10251035

10261036
@pytest.mark.parametrize(
@@ -1055,11 +1065,16 @@ def test_request_source_if_duration_over_threshold_span_streaming(
10551065
http_span = _get_http_client_span(items)
10561066

10571067
assert "code.line.number" in http_span["attributes"]
1068+
assert SPANDATA.CODE_NAMESPACE in http_span["attributes"]
10581069
assert "code.file.path" in http_span["attributes"]
1059-
assert "code.function.name" in http_span["attributes"]
1070+
assert SPANDATA.CODE_FUNCTION in http_span["attributes"]
10601071

10611072
assert type(http_span["attributes"]["code.line.number"]) == int
10621073
assert http_span["attributes"]["code.line.number"] > 0
1074+
assert (
1075+
http_span["attributes"][SPANDATA.CODE_NAMESPACE]
1076+
== "tests.integrations.httpx.test_httpx"
1077+
)
10631078
assert http_span["attributes"]["code.file.path"].endswith(
10641079
"tests/integrations/httpx/test_httpx.py"
10651080
)
@@ -1068,7 +1083,7 @@ def test_request_source_if_duration_over_threshold_span_streaming(
10681083
assert is_relative_path
10691084

10701085
assert (
1071-
http_span["attributes"]["code.function.name"]
1086+
http_span["attributes"][SPANDATA.CODE_FUNCTION]
10721087
== "test_request_source_if_duration_over_threshold_span_streaming"
10731088
)
10741089

0 commit comments

Comments
 (0)