@@ -69,7 +69,7 @@ def report_error_on_span(error: str, message: str) -> None:
69
69
if not span :
70
70
root_span = core .get_root_span ()
71
71
else :
72
- root_span = span . _local_root or span
72
+ root_span = get_service_entry_span ( span )
73
73
if not root_span :
74
74
return
75
75
root_span .set_tag_str (APPSEC .ERROR_TYPE , error )
@@ -118,6 +118,17 @@ def in_asm_context() -> bool:
118
118
return core .get_item (_ASM_CONTEXT ) is not None
119
119
120
120
121
+ def get_service_entry_span (span : Span ) -> Span :
122
+ """Find the service entry span of a span
123
+
124
+ We can't simply go for the span._local_root
125
+ because it may belong to another service.
126
+ """
127
+ while not span ._is_top_level and span ._parent :
128
+ span = span ._parent
129
+ return span
130
+
131
+
121
132
def is_blocked () -> bool :
122
133
env = _get_asm_context ()
123
134
if env is None :
@@ -194,7 +205,7 @@ def flush_waf_triggers(env: ASM_Environment) -> None:
194
205
from ddtrace .appsec ._metrics import ddwaf_version
195
206
196
207
# Make sure we find a root span to attach the triggers to
197
- root_span = env .span . _local_root or env . span
208
+ root_span = get_service_entry_span ( env .span )
198
209
if env .waf_triggers :
199
210
report_list = get_triggers (root_span )
200
211
if report_list is not None :
@@ -240,7 +251,7 @@ def finalize_asm_env(env: ASM_Environment) -> None:
240
251
flush_waf_triggers (env )
241
252
for function in env .callbacks [_CONTEXT_CALL ]:
242
253
function (env )
243
- root_span = env .span . _local_root or env . span
254
+ root_span = get_service_entry_span ( env .span )
244
255
if root_span :
245
256
if env .waf_info :
246
257
info = env .waf_info ()
@@ -255,7 +266,7 @@ def finalize_asm_env(env: ASM_Environment) -> None:
255
266
except Exception :
256
267
logger .debug ("asm_context::finalize_asm_env::exception" , extra = log_extra , exc_info = True )
257
268
if asm_config ._rc_client_id is not None :
258
- root_span ._local_root . set_tag (APPSEC .RC_CLIENT_ID , asm_config ._rc_client_id )
269
+ root_span .set_tag (APPSEC .RC_CLIENT_ID , asm_config ._rc_client_id )
259
270
waf_adresses = env .waf_addresses
260
271
req_headers = waf_adresses .get (SPAN_DATA_NAMES .REQUEST_HEADERS_NO_COOKIES , {})
261
272
if req_headers :
@@ -661,7 +672,7 @@ def _set_headers(span: Span, headers: Any, kind: str, only_asm_enabled: bool = F
661
672
value = value .decode ()
662
673
if key .lower () in (_COLLECTED_REQUEST_HEADERS_ASM_ENABLED if only_asm_enabled else _COLLECTED_REQUEST_HEADERS ):
663
674
# since the header value can be a list, use `set_tag()` to ensure it is converted to a string
664
- ( span . _local_root or span ).set_tag (_normalize_tag_name (kind , key ), value )
675
+ get_service_entry_span ( span ).set_tag (_normalize_tag_name (kind , key ), value )
665
676
666
677
667
678
def asm_listen ():
0 commit comments