Skip to content
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
2 changes: 1 addition & 1 deletion src/uipath/tracing/_live_tracking_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _upsert_span_async(

def _upsert():
try:
if status_override:
if status_override is not None:
self.exporter.upsert_span(span, status_override=status_override)
else:
self.exporter.upsert_span(span)
Expand Down
42 changes: 23 additions & 19 deletions src/uipath/tracing/_otel_exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,28 +326,32 @@ def _process_span_attributes(self, span_data: Dict[str, Any]) -> None:
else:
return

# Determine SpanType
if "openinference.span.kind" in attributes:
# Determine SpanType from OpenInference spans
is_openinference = "openinference.span.kind" in attributes
if is_openinference:
span_type = attributes["openinference.span.kind"]
span_data["SpanType"] = self.SPAN_TYPE_MAPPING.get(span_type, span_type)

# Apply basic attribute mapping
for old_key, mapping in self.ATTRIBUTE_MAPPING.items():
if old_key in attributes:
if isinstance(mapping, tuple):
new_key, func = mapping
attributes[new_key] = func(attributes[old_key])
else:
new_key = mapping
attributes[new_key] = attributes[old_key]

# Apply detailed mapping based on SpanType
# Modify attributes dict in place to avoid allocations
span_type = span_data.get("SpanType")
if span_type == "completion":
self._map_llm_call_attributes(attributes)
elif span_type == "toolCall":
self._map_tool_call_attributes(attributes)
# Apply basic attribute mapping (only for OpenInference spans)
if is_openinference:
for old_key, mapping in self.ATTRIBUTE_MAPPING.items():
if old_key in attributes:
if isinstance(mapping, tuple):
new_key, func = mapping
attributes[new_key] = func(attributes[old_key])
else:
new_key = mapping
attributes[new_key] = attributes[old_key]

# Apply detailed mapping based on SpanType (only for OpenInference spans)
# These mappings convert OpenInference-format attributes to UiPath format.
# Agent manual spans (from UiPathTracer) already have correctly formatted attributes.
if is_openinference:
span_type = span_data.get("SpanType")
if span_type == "completion":
self._map_llm_call_attributes(attributes)
elif span_type == "toolCall":
self._map_tool_call_attributes(attributes)

# Parse JSON-encoded strings that should be objects (avoids double-encoding)
# OTEL only accepts primitives, so agents serialize dicts to JSON strings.
Expand Down
2 changes: 1 addition & 1 deletion src/uipath/tracing/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def otel_span_to_uipath_span(
reference_id = attributes_dict.get("referenceId")

# Source: override via uipath.source attribute, else DEFAULT_SOURCE
uipath_source = attributes_dict.get("uipath.source")
uipath_source = attributes_dict.get("uipath.source", attributes_dict.get("source"))
source = uipath_source if isinstance(uipath_source, int) else DEFAULT_SOURCE

attachments = None
Expand Down
Loading