Skip to content

Commit 090a043

Browse files
refactor(platform): use UiPathConfig for trace context, expose extra_baggage API
Replace direct os.getenv() calls with UiPathConfig properties and remove hardcoded source=agents baggage to keep uipath-platform framework-agnostic. Add extra_baggage parameter so integration repos can inject their own entries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 320590d commit 090a043

3 files changed

Lines changed: 42 additions & 19 deletions

File tree

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
"""W3C-style trace context headers for LLM Gateway requests."""
22

3-
import os
4-
53
from opentelemetry import trace
64
from uipath.core.feature_flags import FeatureFlags
75

8-
from ..common.constants import (
9-
ENV_FOLDER_KEY,
10-
ENV_PROCESS_KEY,
11-
ENV_UIPATH_PROCESS_UUID,
12-
)
6+
from ..common._config import UiPathConfig
137

148

15-
def build_trace_context_headers() -> dict[str, str]:
9+
def build_trace_context_headers(
10+
extra_baggage: list[str] | None = None,
11+
) -> dict[str, str]:
1612
"""Build W3C-style trace context headers from the current OpenTelemetry span.
1713
14+
Args:
15+
extra_baggage: Additional baggage entries (e.g. ``["source=agents"]``)
16+
that callers can inject alongside the platform-level entries.
17+
1818
Returns an empty dict when the ``EnableTraceContextHeaders`` feature flag
1919
is not enabled, or when no active span is present.
2020
"""
@@ -29,13 +29,14 @@ def build_trace_context_headers() -> dict[str, str]:
2929
span_id = format(ctx.span_id, "016x")
3030
headers["x-uipath-traceparent-id"] = f"00-{trace_id}-{span_id}"
3131

32-
baggage_parts: list[str] = ["source=agents"]
33-
if folder_key := os.getenv(ENV_FOLDER_KEY):
32+
baggage_parts: list[str] = list(extra_baggage) if extra_baggage else []
33+
if folder_key := UiPathConfig.folder_key:
3434
baggage_parts.append(f"folderKey={folder_key}")
35-
if agent_id := os.getenv(ENV_UIPATH_PROCESS_UUID):
35+
if agent_id := UiPathConfig.process_uuid:
3636
baggage_parts.append(f"agentId={agent_id}")
37-
if process_key := os.getenv(ENV_PROCESS_KEY):
37+
if process_key := UiPathConfig.process_key:
3838
baggage_parts.append(f"processKey={process_key}")
39-
headers["x-uipath-tracebaggage"] = ",".join(baggage_parts)
39+
if baggage_parts:
40+
headers["x-uipath-tracebaggage"] = ",".join(baggage_parts)
4041

4142
return headers

packages/uipath-platform/src/uipath/platform/common/_config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ def folder_path(self) -> str | None:
121121

122122
return os.getenv(ENV_FOLDER_PATH, None)
123123

124+
@property
125+
def process_key(self) -> str | None:
126+
from uipath.platform.common.constants import ENV_PROCESS_KEY
127+
128+
return os.getenv(ENV_PROCESS_KEY, None)
129+
124130
@property
125131
def process_uuid(self) -> str | None:
126132
from uipath.platform.common.constants import ENV_UIPATH_PROCESS_UUID

packages/uipath-platform/tests/services/test_llm_trace_context.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def test_no_traceparent_without_active_span(self) -> None:
7575

7676

7777
class TestBaggageHeader:
78-
"""When enabled, x-uipath-tracebaggage is populated from env vars."""
78+
"""When enabled, x-uipath-tracebaggage is populated from UiPathConfig."""
7979

8080
def setup_method(self) -> None:
8181
FeatureFlags.reset_flags()
@@ -91,7 +91,6 @@ def test_all_env_vars_present(self) -> None:
9191
headers = build_trace_context_headers()
9292

9393
baggage = headers["x-uipath-tracebaggage"]
94-
assert "source=agents" in baggage
9594
assert "folderKey=folder-abc" in baggage
9695
assert "agentId=agent-123" in baggage
9796
assert "processKey=process-789" in baggage
@@ -102,14 +101,13 @@ def test_partial_env_vars(self) -> None:
102101
headers = build_trace_context_headers()
103102

104103
baggage = headers["x-uipath-tracebaggage"]
105-
assert "source=agents" in baggage
106104
assert "folderKey=folder-only" in baggage
107105

108-
def test_always_includes_source(self) -> None:
106+
def test_no_baggage_without_env_vars(self) -> None:
109107
with patch.dict(os.environ, {}, clear=True):
110108
headers = build_trace_context_headers()
111109

112-
assert headers["x-uipath-tracebaggage"] == "source=agents"
110+
assert "x-uipath-tracebaggage" not in headers
113111

114112
def test_baggage_comma_separated(self) -> None:
115113
env = {
@@ -121,7 +119,25 @@ def test_baggage_comma_separated(self) -> None:
121119

122120
baggage = headers["x-uipath-tracebaggage"]
123121
parts = baggage.split(",")
124-
assert len(parts) == 3 # source + folderKey + agentId
122+
assert len(parts) == 2 # folderKey + agentId
123+
124+
def test_extra_baggage_included(self) -> None:
125+
env = {"UIPATH_FOLDER_KEY": "f1"}
126+
with patch.dict(os.environ, env, clear=True):
127+
headers = build_trace_context_headers(extra_baggage=["source=agents"])
128+
129+
baggage = headers["x-uipath-tracebaggage"]
130+
assert "source=agents" in baggage
131+
assert "folderKey=f1" in baggage
132+
133+
def test_extra_baggage_only(self) -> None:
134+
with patch.dict(os.environ, {}, clear=True):
135+
headers = build_trace_context_headers(
136+
extra_baggage=["source=agents", "custom=value"]
137+
)
138+
139+
baggage = headers["x-uipath-tracebaggage"]
140+
assert baggage == "source=agents,custom=value"
125141

126142

127143
class TestBothHeaders:

0 commit comments

Comments
 (0)