Skip to content
This repository was archived by the owner on Mar 4, 2026. It is now read-only.

Commit 6ee0c67

Browse files
committed
wip2 chains
1 parent 4b7af71 commit 6ee0c67

1 file changed

Lines changed: 74 additions & 76 deletions

File tree

src/uipath/core/tracing/manager.py

Lines changed: 74 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,43 @@ def get_parent_context() -> context.Context:
6161
)
6262
return set_span_in_context(bottom_span)
6363

64+
@staticmethod
65+
def _build_ancestor_chain(span: ReadableSpan, spans_by_id: dict) -> List[ReadableSpan]:
66+
"""Build a complete ancestor chain by traversing parents.
67+
68+
Args:
69+
span: The starting span
70+
spans_by_id: Dictionary to populate with discovered spans
71+
72+
Returns:
73+
List of ancestors from bottom (the span) to top (root)
74+
"""
75+
chain = []
76+
current = span
77+
visited = set()
78+
79+
while current:
80+
span_id = current.get_span_context().span_id
81+
82+
# Avoid infinite loops
83+
if span_id in visited:
84+
break
85+
visited.add(span_id)
86+
87+
chain.append(current)
88+
spans_by_id[span_id] = current
89+
90+
# Move to parent if it exists
91+
if current.parent:
92+
parent_id = current.parent.span_id
93+
# Try to get parent from already known spans
94+
current = spans_by_id.get(parent_id)
95+
# If not found, we can't traverse further
96+
else:
97+
break
98+
99+
return chain
100+
64101
@staticmethod
65102
def _get_bottom_most_span(
66103
current_span: ReadableSpan, external_span: ReadableSpan
@@ -80,102 +117,63 @@ def _get_bottom_most_span(
80117
current_span_id = current_span.get_span_context().span_id
81118
external_span_id = external_span.get_span_context().span_id
82119

83-
current_parent_id = (
84-
f"{current_span.parent.span_id:016x}" if current_span.parent else "None"
85-
)
86-
external_parent_id = (
87-
f"{external_span.parent.span_id:016x}" if external_span.parent else "None"
88-
)
89-
90-
logger.info(
91-
f"current_span: '{current_span.name}' (id: {current_span_id:016x}, parent: {current_parent_id})"
92-
)
93-
logger.info(
94-
f"external_span: '{external_span.name}' (id: {external_span_id:016x}, parent: {external_parent_id})"
95-
)
96-
97-
# Build complete ancestor chain by combining external ancestors with both spans
120+
# Start by adding external ancestors to our known spans
98121
external_ancestors = UiPathTracingManager.get_ancestor_spans() or []
99-
100-
# Create a map of all known spans by ID
101122
spans_by_id = {}
102123
for ancestor in external_ancestors:
103124
spans_by_id[ancestor.get_span_context().span_id] = ancestor
104125

105-
# Add both current spans to the map
106-
spans_by_id[current_span_id] = current_span
107-
spans_by_id[external_span_id] = external_span
126+
# Build complete ancestor chains for both spans
127+
logger.info("Building ancestor chain for current_span...")
128+
current_chain = UiPathTracingManager._build_ancestor_chain(current_span, spans_by_id)
108129

109-
logger.info(f"Total known spans: {len(spans_by_id)}")
110-
logger.info("All known spans:")
111-
for span in spans_by_id.values():
112-
span_id = span.get_span_context().span_id
113-
parent_id = f"{span.parent.span_id:016x}" if span.parent else "None"
114-
logger.info(f" {span.name} (id: {span_id:016x}, parent: {parent_id})")
130+
logger.info("Building ancestor chain for external_span...")
131+
external_chain = UiPathTracingManager._build_ancestor_chain(external_span, spans_by_id)
115132

116-
# Check direct parent-child relationships
117-
current_parent = current_span.parent
118-
external_parent = external_span.parent
133+
logger.info(f"current_span chain length (depth): {len(current_chain)}")
134+
logger.info(f"external_span chain length (depth): {len(external_chain)}")
119135

120-
# Check if current_span is a child of external_span
121-
if current_parent and current_parent.span_id == external_span_id:
122-
logger.info(f"RESULT: current_span '{current_span.name}' is a direct child of external_span -> returning current_span")
123-
logger.info("=" * 80)
124-
return current_span
125-
126-
# Check if external_span is a child of current_span
127-
if external_parent and external_parent.span_id == current_span_id:
128-
logger.info(f"RESULT: external_span '{external_span.name}' is a direct child of current_span -> returning external_span")
129-
logger.info("=" * 80)
130-
return external_span
136+
# Log the chains
137+
logger.info("current_span chain (bottom to top):")
138+
for i, span in enumerate(current_chain):
139+
span_id = span.get_span_context().span_id
140+
parent_id = f"{span.parent.span_id:016x}" if span.parent else "None"
141+
logger.info(f" [{i}] {span.name} (id: {span_id:016x}, parent: {parent_id})")
131142

132-
# Check if parents are in the known spans - find which one is deeper
133-
current_parent_span = spans_by_id.get(current_parent.span_id) if current_parent else None
134-
external_parent_span = spans_by_id.get(external_parent.span_id) if external_parent else None
143+
logger.info("external_span chain (bottom to top):")
144+
for i, span in enumerate(external_chain):
145+
span_id = span.get_span_context().span_id
146+
parent_id = f"{span.parent.span_id:016x}" if span.parent else "None"
147+
logger.info(f" [{i}] {span.name} (id: {span_id:016x}, parent: {parent_id})")
135148

136-
if current_parent_span and not external_parent_span:
137-
logger.info("RESULT: current_span has a parent in the tree, external_span doesn't -> returning current_span")
149+
# The span with the longer chain is deeper
150+
if len(current_chain) > len(external_chain):
151+
logger.info(f"RESULT: current_span is deeper (chain length {len(current_chain)} > {len(external_chain)}) -> returning current_span")
138152
logger.info("=" * 80)
139153
return current_span
140-
141-
if external_parent_span and not current_parent_span:
142-
logger.info("RESULT: external_span has a parent in the tree, current_span doesn't -> returning external_span")
154+
elif len(external_chain) > len(current_chain):
155+
logger.info(f"RESULT: external_span is deeper (chain length {len(external_chain)} > {len(current_chain)}) -> returning external_span")
143156
logger.info("=" * 80)
144157
return external_span
158+
else:
159+
# Same depth - check if one is an ancestor of the other
160+
current_span_ids = {s.get_span_context().span_id for s in current_chain}
161+
external_span_ids = {s.get_span_context().span_id for s in external_chain}
145162

146-
# Both have parents in the tree - need to determine which is deeper
147-
# Calculate depth by traversing parent chains
148-
if current_parent_span and external_parent_span:
149-
current_depth = 0
150-
external_depth = 0
151-
152-
# Count current_span ancestors
153-
temp_span = current_span
154-
while temp_span and temp_span.parent:
155-
current_depth += 1
156-
temp_span = spans_by_id.get(temp_span.parent.span_id)
157-
158-
# Count external_span ancestors
159-
temp_span = external_span
160-
while temp_span and temp_span.parent:
161-
external_depth += 1
162-
temp_span = spans_by_id.get(temp_span.parent.span_id)
163-
164-
logger.info(f"current_span depth: {current_depth}, external_span depth: {external_depth}")
165-
166-
if current_depth > external_depth:
167-
logger.info(f"RESULT: current_span is deeper (depth {current_depth} > {external_depth}) -> returning current_span")
163+
if external_span_id in current_span_ids:
164+
logger.info("RESULT: external_span is in current_span's chain -> returning current_span (deeper)")
168165
logger.info("=" * 80)
169166
return current_span
170-
else:
171-
logger.info(f"RESULT: external_span is deeper (depth {external_depth} >= {current_depth}) -> returning external_span")
167+
168+
if current_span_id in external_span_ids:
169+
logger.info("RESULT: current_span is in external_span's chain -> returning external_span (deeper)")
172170
logger.info("=" * 80)
173171
return external_span
174172

175-
# Default: return external_span
176-
logger.info(f"RESULT: Cannot determine hierarchy -> defaulting to external_span '{external_span.name}'")
177-
logger.info("=" * 80)
178-
return external_span
173+
# Same depth, different branches - default to external
174+
logger.info(f"RESULT: Same depth ({len(current_chain)}), different branches -> defaulting to external_span")
175+
logger.info("=" * 80)
176+
return external_span
179177

180178
@staticmethod
181179
def get_external_current_span():

0 commit comments

Comments
 (0)