uipath-core 0.1.6__py3-none-any.whl → 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,8 +6,10 @@ import random
6
6
  from functools import wraps
7
7
  from typing import Any, Callable, Optional
8
8
 
9
+ from opentelemetry import context as context_api
9
10
  from opentelemetry import trace
10
- from opentelemetry.trace import NonRecordingSpan, SpanContext, TraceFlags
11
+ from opentelemetry.context import _SUPPRESS_INSTRUMENTATION_KEY
12
+ from opentelemetry.trace import SpanContext, TraceFlags
11
13
  from opentelemetry.trace.status import StatusCode
12
14
 
13
15
  from uipath.core.tracing._utils import (
@@ -15,7 +17,11 @@ from uipath.core.tracing._utils import (
15
17
  set_span_input_attributes,
16
18
  set_span_output_attributes,
17
19
  )
18
- from uipath.core.tracing.span_utils import UiPathSpanUtils
20
+ from uipath.core.tracing.span_utils import (
21
+ ParentedNonRecordingSpan,
22
+ UiPathSpanUtils,
23
+ _span_registry,
24
+ )
19
25
 
20
26
  logger = logging.getLogger(__name__)
21
27
 
@@ -48,7 +54,10 @@ def _opentelemetry_traced(
48
54
  trace_name = name or func.__name__
49
55
 
50
56
  def get_span():
57
+ ctx = UiPathSpanUtils.get_parent_context()
51
58
  if not recording:
59
+ parent_context = trace.get_current_span(ctx).get_span_context()
60
+
52
61
  # Create a valid but non-sampled trace context
53
62
  # Generate a valid trace ID (not INVALID)
54
63
  trace_id = random.getrandbits(128)
@@ -60,24 +69,30 @@ def _opentelemetry_traced(
60
69
  is_remote=False,
61
70
  trace_flags=TraceFlags(0x00), # NOT sampled
62
71
  )
63
- non_recording = NonRecordingSpan(non_sampled_context)
72
+ non_recording = ParentedNonRecordingSpan(
73
+ non_sampled_context, parent=parent_context
74
+ )
64
75
 
65
76
  # Make it active so children see it
66
77
  span_cm = trace.use_span(non_recording)
67
78
  span_cm.__enter__()
68
- return span_cm, non_recording
69
79
 
70
- # Normal recording span
71
- ctx = UiPathSpanUtils.get_parent_context()
72
- span_cm = trace.get_tracer(__name__).start_as_current_span(
73
- trace_name, context=ctx
74
- )
75
- span = span_cm.__enter__()
76
- return span_cm, span
80
+ _span_registry.register_span(non_recording)
81
+
82
+ return span_cm, non_recording
83
+ else:
84
+ # Normal recording span
85
+ span_cm = trace.get_tracer(__name__).start_as_current_span(
86
+ trace_name, context=ctx
87
+ )
88
+ span = span_cm.__enter__()
89
+ return span_cm, span
77
90
 
78
91
  # --------- Sync wrapper ---------
79
92
  @wraps(func)
80
93
  def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
94
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
95
+ return func(*args, **kwargs)
81
96
  span_cm, span = get_span()
82
97
  try:
83
98
  # Set input attributes BEFORE execution
@@ -113,6 +128,8 @@ def _opentelemetry_traced(
113
128
  # --------- Async wrapper ---------
114
129
  @wraps(func)
115
130
  async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
131
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
132
+ return await func(*args, **kwargs)
116
133
  span_cm, span = get_span()
117
134
  try:
118
135
  # Set input attributes BEFORE execution
@@ -148,6 +165,10 @@ def _opentelemetry_traced(
148
165
  # --------- Generator wrapper ---------
149
166
  @wraps(func)
150
167
  def generator_wrapper(*args: Any, **kwargs: Any) -> Any:
168
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
169
+ for item in func(*args, **kwargs):
170
+ yield item
171
+ return
151
172
  span_cm, span = get_span()
152
173
  try:
153
174
  # Set input attributes BEFORE execution
@@ -186,6 +207,10 @@ def _opentelemetry_traced(
186
207
  # --------- Async generator wrapper ---------
187
208
  @wraps(func)
188
209
  async def async_generator_wrapper(*args: Any, **kwargs: Any) -> Any:
210
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
211
+ async for item in func(*args, **kwargs):
212
+ yield item
213
+ return
189
214
  span_cm, span = get_span()
190
215
  try:
191
216
  # Set input attributes BEFORE execution
@@ -4,11 +4,33 @@ import logging
4
4
  from typing import Callable, Optional
5
5
 
6
6
  from opentelemetry import context, trace
7
- from opentelemetry.trace import Span, set_span_in_context
7
+ from opentelemetry.trace import NonRecordingSpan, Span, set_span_in_context
8
8
 
9
9
  logger = logging.getLogger(__name__)
10
10
 
11
11
 
12
+ class ParentedNonRecordingSpan(NonRecordingSpan):
13
+ """Non-recording span with explicit parent tracking.
14
+
15
+ Extends NonRecordingSpan to include a parent attribute, allowing the SpanRegistry
16
+ to properly track parent-child relationships for non-recording spans.
17
+ This is necessary because NonRecordingSpan instances created directly don't have
18
+ their parent automatically set like normal recording spans do.
19
+ """
20
+
21
+ def __init__(
22
+ self, context: trace.SpanContext, parent: Optional[trace.SpanContext] = None
23
+ ):
24
+ """Initialize a parented non-recording span.
25
+
26
+ Args:
27
+ context: The SpanContext for this span
28
+ parent: Optional parent SpanContext
29
+ """
30
+ super().__init__(context)
31
+ self.parent = parent
32
+
33
+
12
34
  class SpanRegistry:
13
35
  """Registry to track all spans and their parent relationships."""
14
36
 
@@ -309,4 +331,4 @@ class UiPathSpanUtils:
309
331
  return UiPathSpanUtils._current_span_ancestors_provider
310
332
 
311
333
 
312
- __all__ = ["UiPathSpanUtils"]
334
+ __all__ = ["ParentedNonRecordingSpan", "UiPathSpanUtils"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath-core
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: UiPath Core abstractions
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-core-python
@@ -20,12 +20,12 @@ uipath/core/guardrails/_evaluators.py,sha256=ovmVm-8iB8Pm9arjG7mHM9-GIRkrG3V6oHR
20
20
  uipath/core/guardrails/guardrails.py,sha256=DraeFkoDKVDnc0EKdFYYP29lQu7U2hneTsj1dxveHU4,4935
21
21
  uipath/core/tracing/__init__.py,sha256=1XNLYZ4J76XkRrizGO486mS6yxzVXUbrldpvxTyJe3E,483
22
22
  uipath/core/tracing/_utils.py,sha256=FiCFGOFa4czruhlSF87Q5Q4jX9KKPHZiw8k14K7W5v4,6636
23
- uipath/core/tracing/decorators.py,sha256=ag_MFwZ0TywrhbpLKqQwF1guvRA9sYiItxao5LN9_Iw,10942
23
+ uipath/core/tracing/decorators.py,sha256=JDNULkUu-Ufg8pJslG4i6Q2pmqaGNDS8NFRPgFs29Dw,11937
24
24
  uipath/core/tracing/exporters.py,sha256=FClouEEQfk3F8J7G_NFoarDJM3R0-gA5jUxA5xRHx5s,1562
25
25
  uipath/core/tracing/processors.py,sha256=R_652rtjPmfpUtaXoIcmfZrRZylVXFRNwjOmJUUxOQw,1408
26
- uipath/core/tracing/span_utils.py,sha256=WYBrd6ZbawAs7r1Js-Zvo9_8GzkD9LhHNOls00bK_xI,12235
26
+ uipath/core/tracing/span_utils.py,sha256=LZXNdnI0-fhKe49CLPsvMJIfh9zdzk8rK4g4YN5RfDU,13064
27
27
  uipath/core/tracing/trace_manager.py,sha256=51rscJcepkTK4bWoCZdE-DFc9wt2F-aSuFBaSXmkHl0,3130
28
- uipath_core-0.1.6.dist-info/METADATA,sha256=R2wS5I85yHd-uTvGgepwbhKiZA7cLb389XJ5R57ED7I,938
29
- uipath_core-0.1.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
30
- uipath_core-0.1.6.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
31
- uipath_core-0.1.6.dist-info/RECORD,,
28
+ uipath_core-0.1.8.dist-info/METADATA,sha256=WaZcOoWscnXrgIhPHw8YATSu8xZ3x64SmndWI5tndG4,938
29
+ uipath_core-0.1.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
30
+ uipath_core-0.1.8.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
31
+ uipath_core-0.1.8.dist-info/RECORD,,