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
10 changes: 7 additions & 3 deletions src/uipath/tracing/_otel_exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
return SpanExportResult.SUCCESS

logger.debug(
f"Exporting {len(spans)} spans to {self.base_url}/llmopstenant_/api/Traces/spans"
f"Exporting {len(spans)} spans to {self.base_url}/api/Traces/spans"
)

# Use optimized path: keep attributes as dict for processing
Expand Down Expand Up @@ -369,7 +369,7 @@ def _process_span_attributes(self, span_data: Dict[str, Any]) -> None:
def _build_url(self, span_list: list[Dict[str, Any]]) -> str:
"""Construct the URL for the API request."""
trace_id = str(span_list[0]["TraceId"])
return f"{self.base_url}/llmopstenant_/api/Traces/spans?traceId={trace_id}&source=Robots"
return f"{self.base_url}/api/Traces/spans?traceId={trace_id}&source=Robots"

def _send_with_retries(
self, url: str, payload: list[Dict[str, Any]], max_retries: int = 4
Expand All @@ -393,14 +393,18 @@ def _send_with_retries(
return SpanExportResult.FAILURE

def _get_base_url(self) -> str:
trace_base_url = os.environ.get("UIPATH_TRACE_BASE_URL")
if trace_base_url:
return trace_base_url.rstrip("/")

uipath_url = (
os.environ.get("UIPATH_URL")
or "https://cloud.uipath.com/dummyOrg/dummyTennant/"
)

uipath_url = uipath_url.rstrip("/")

return uipath_url
return f"{uipath_url}/llmopstenant_"


class JsonLinesFileExporter(SpanExporter):
Expand Down
45 changes: 40 additions & 5 deletions tests/tracing/test_otel_exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_init_with_env_vars(mock_env_vars):
with patch("uipath.tracing._otel_exporters.httpx.Client"):
exporter = LlmOpsHttpExporter()

assert exporter.base_url == "https://test.uipath.com/org/tenant"
assert exporter.base_url == "https://test.uipath.com/org/tenant/llmopstenant_"
assert exporter.auth_token == "test-token"
assert exporter.headers == {
"Content-Type": "application/json",
Expand All @@ -80,7 +80,10 @@ def test_init_with_default_url():
):
exporter = LlmOpsHttpExporter()

assert exporter.base_url == "https://cloud.uipath.com/dummyOrg/dummyTennant"
assert (
exporter.base_url
== "https://cloud.uipath.com/dummyOrg/dummyTennant/llmopstenant_"
)
assert exporter.auth_token == "test-token"


Expand Down Expand Up @@ -164,21 +167,53 @@ def test_get_base_url():
):
with patch("uipath.tracing._otel_exporters.httpx.Client"):
exporter = LlmOpsHttpExporter()
assert exporter.base_url == "https://custom.uipath.com/org/tenant"
assert (
exporter.base_url
== "https://custom.uipath.com/org/tenant/llmopstenant_"
)

# Test with environment variable set but with no trailing slash
with patch.dict(
os.environ, {"UIPATH_URL": "https://custom.uipath.com/org/tenant"}, clear=True
):
with patch("uipath.tracing._otel_exporters.httpx.Client"):
exporter = LlmOpsHttpExporter()
assert exporter.base_url == "https://custom.uipath.com/org/tenant"
assert (
exporter.base_url
== "https://custom.uipath.com/org/tenant/llmopstenant_"
)

# Test with no environment variable
with patch.dict(os.environ, {}, clear=True):
with patch("uipath.tracing._otel_exporters.httpx.Client"):
exporter = LlmOpsHttpExporter()
assert exporter.base_url == "https://cloud.uipath.com/dummyOrg/dummyTennant"
assert (
exporter.base_url
== "https://cloud.uipath.com/dummyOrg/dummyTennant/llmopstenant_"
)

# Test UIPATH_TRACE_BASE_URL takes precedence over UIPATH_URL
with patch.dict(
os.environ,
{
"UIPATH_TRACE_BASE_URL": "https://custom-trace.example.com/my_prefix",
"UIPATH_URL": "https://custom.uipath.com/org/tenant",
},
clear=True,
):
with patch("uipath.tracing._otel_exporters.httpx.Client"):
exporter = LlmOpsHttpExporter()
assert exporter.base_url == "https://custom-trace.example.com/my_prefix"

# Test UIPATH_TRACE_BASE_URL strips trailing slash
with patch.dict(
os.environ,
{"UIPATH_TRACE_BASE_URL": "https://custom-trace.example.com/prefix/"},
clear=True,
):
with patch("uipath.tracing._otel_exporters.httpx.Client"):
exporter = LlmOpsHttpExporter()
assert exporter.base_url == "https://custom-trace.example.com/prefix"


def test_send_with_retries_success():
Expand Down