Skip to content

feat: add ReferenceContext for span reference hierarchy propagation#1708

Open
jepadil23 wants to merge 10 commits into
mainfrom
feat/reference-hierarchy-context
Open

feat: add ReferenceContext for span reference hierarchy propagation#1708
jepadil23 wants to merge 10 commits into
mainfrom
feat/reference-hierarchy-context

Conversation

@jepadil23

Copy link
Copy Markdown

Summary

  • Adds ReferenceContext — an immutable, copy-on-write ordered list of ReferenceEntry objects (serviceType, referenceId, version) that flows via contextvars.ContextVar across await boundaries
  • _span_utils.py reads from ReferenceContextAccessor to populate UiPathSpan.context.referenceHierarchy — wire-format compatible with service-common x-uipath-tracebaggage header
  • Fixes BatchSpanProcessor thread-boundary issue by stamping the hierarchy as a span attribute at span start
  • Normalizes empty-string env vars (UIPATH_ORGANIZATION_ID, UIPATH_TENANT_ID, UIPATH_FOLDER_KEY) to None for Guid fields in UiPathSpan

Test plan

  • tests/services/test_reference_context.py — unit tests for ReferenceContext, ReferenceEntry, and ReferenceContextAccessor (push/pop/reset, async propagation, wire serialization)
  • Verify UiPathSpan.context.referenceHierarchy is populated when ReferenceContextAccessor has entries set upstream
  • Verify empty-string env vars normalize to None in span fields

🤖 Generated with Claude Code

jepadil23 and others added 3 commits June 8, 2026 21:12
Introduces an immutable, copy-on-write ReferenceContext (modelled after
service-common BaggageContext) that propagates the reference hierarchy
through all spans emitted to LLMOps/Traceview.

- `_reference_context.py`: ReferenceEntry, ReferenceContext (add /
  to_wire_list / from_baggage_header / to_baggage_header_value),
  ReferenceContextAccessor (ContextVar-backed, async-safe)
- `_span_utils.py`: UiPathSpan gains `context` field; to_dict() emits
  `Context.referenceHierarchy` when set; otel_span_to_uipath_span()
  reads ReferenceContextAccessor and builds the wire payload
- `uipath.tracing`: re-exports ReferenceEntry, ReferenceContext,
  ReferenceContextAccessor for downstream consumers
- Tests: 30 new tests covering immutability, wire format, baggage
  header round-trip, accessor lifecycle, and span wiring

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…hSpan

UIPATH_FOLDER_KEY, UIPATH_ORGANIZATION_ID, and UIPATH_TENANT_ID default
to "" when unset. SpanReq.FolderKey is Guid? on the server — sending ""
causes a JSON deserialization exception ("could not convert to
System.Nullable[Guid]") which cascades into "The spans field is required"
from ASP.NET's model binding. Normalize all three to None so unset vars
serialize as null instead of an unparseable empty string.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…Processor thread boundary

ContextVar values are not propagated to background threads. The
BatchSpanProcessor exports spans in a worker thread where
ReferenceContextAccessor.get() always returns None, so Context.referenceHierarchy
was never populated in the wire payload.

Fix: register a span-start hook (_inject_reference_hierarchy) that runs
synchronously in on_start — same thread/context as the span creator — reads
the ambient ReferenceContext and stamps it as uipath.reference_hierarchy on the
span. The attribute travels with the span to the export thread.
otel_span_to_uipath_span now reads from the attribute instead of the ContextVar,
and pops it from attributes_dict so it does not appear in the wire Attributes field.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 10, 2026 19:10
@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-runtime test:uipath-integrations labels Jun 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new reference-hierarchy propagation mechanism for spans by introducing an immutable ReferenceContext carried via contextvars, stamping the hierarchy onto spans at start-time to survive BatchSpanProcessor thread boundaries, and wiring that stamped hierarchy into the UiPath span wire payload (Context.referenceHierarchy).

Changes:

  • Introduces ReferenceContext / ReferenceEntry plus a ReferenceContextAccessor backed by ContextVar.
  • Adds a span-start hook mechanism in core tracing processors and uses it in _span_utils.py to stamp uipath.reference_hierarchy at span creation time.
  • Extends UiPathSpan serialization to emit a top-level Context field and normalizes empty-string org/tenant/folder env vars to None.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
packages/uipath/src/uipath/tracing/init.py Re-exports ReferenceContext* types from platform common tracing surface.
packages/uipath-platform/src/uipath/platform/common/_reference_context.py Adds the new immutable reference hierarchy model + ContextVar accessor + header (de)serialization.
packages/uipath-platform/src/uipath/platform/common/_span_utils.py Registers a span-start hook to stamp hierarchy and wires stamped hierarchy into UiPathSpan.Context.
packages/uipath-platform/src/uipath/platform/common/init.py Exposes ReferenceContext* from uipath.platform.common.
packages/uipath-core/src/uipath/core/tracing/processors.py Adds global span-start hook registration and invokes hooks in on_start.
packages/uipath-platform/tests/services/test_reference_context.py Adds unit tests for the new reference context model + span wiring behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/uipath-core/src/uipath/core/tracing/processors.py Outdated
Comment thread packages/uipath-platform/src/uipath/platform/common/_reference_context.py Outdated
Comment thread packages/uipath-platform/src/uipath/platform/common/_reference_context.py Outdated
Comment thread packages/uipath-platform/src/uipath/platform/common/_reference_context.py Outdated
Comment thread packages/uipath-platform/tests/services/test_reference_context.py Outdated
Comment thread packages/uipath-platform/tests/services/test_reference_context.py Outdated
Comment thread packages/uipath-core/src/uipath/core/tracing/processors.py Outdated
@saksharthakkar

Copy link
Copy Markdown
Contributor

You'll need to bump up the version here and then use it in other repos.

@saksharthakkar

Copy link
Copy Markdown
Contributor

Please make sure to address the review comments by Copilot and address these CI requirements
CI / check-dependency-bumps / check-dependency-bumps (pull_request)
CI / check-dependency-bumps / check-dependency-bumps (pull_request)Failing after 8s
CI / check-versions / check-version-availability (pull_request)
CI / check-versions / check-version-availability (pull_request)Failing after 6s
CI / lint / Lint (pull_request)
CI / lint / Lint (pull_request)Failing after 4s
Required
CI / lint / Lint uipath-platform (pull_request)
CI / lint / Lint uipath-platform (pull_request)Failing after 19s

jepadil23 and others added 4 commits July 6, 2026 00:42
Introduces an immutable, copy-on-write ReferenceContext (modelled after
service-common BaggageContext) that propagates the reference hierarchy
through all spans emitted to LLMOps/Traceview.

- `_reference_context.py`: ReferenceEntry, ReferenceContext (add /
  to_wire_list / from_baggage_header / to_baggage_header_value),
  ReferenceContextAccessor (ContextVar-backed, async-safe)
- `_span_utils.py`: UiPathSpan gains `context` field; to_dict() emits
  `Context.referenceHierarchy` when set; otel_span_to_uipath_span()
  reads ReferenceContextAccessor and builds the wire payload
- `uipath.tracing`: re-exports ReferenceEntry, ReferenceContext,
  ReferenceContextAccessor for downstream consumers
- Tests: 30 new tests covering immutability, wire format, baggage
  header round-trip, accessor lifecycle, and span wiring

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…Processor thread boundary

ContextVar values are not propagated to background threads. The
BatchSpanProcessor exports spans in a worker thread where
ReferenceContextAccessor.get() always returns None, so Context.referenceHierarchy
was never populated in the wire payload.

Fix: register a span-start hook (_inject_reference_hierarchy) that runs
synchronously in on_start — same thread/context as the span creator — reads
the ambient ReferenceContext and stamps it as uipath.reference_hierarchy on the
span. The attribute travels with the span to the export thread.
otel_span_to_uipath_span now reads from the attribute instead of the ContextVar,
and pops it from attributes_dict so it does not appear in the wire Attributes field.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

🚨 Heads up: uipath-integrations cross-tests are FAILING 🚨

Your changes may break one or more integrations in uipath-integrations-python:

  • uipath-openai-agents
  • uipath-google-adk
  • uipath-agent-framework
  • uipath-llamaindex
  • uipath-pydantic-ai

⚠️ These checks are NOT enforced by branch protection rules. Please review the failures before merging.

🔍 Inspect the failed run →

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

🚨 Heads up: uipath-langchain cross-tests are FAILING 🚨

Your changes may break the uipath-langchain-python integration.

⚠️ These checks are NOT enforced by branch protection rules. Please review the failures before merging.

🔍 Inspect the failed run →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:uipath-integrations test:uipath-langchain Triggers tests in the uipath-langchain-python repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants