ioa-observe-sdk 1.0.13__py3-none-any.whl → 1.0.15__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.
@@ -21,6 +21,7 @@ def task(
21
21
  name: Optional[str] = None,
22
22
  description: Optional[str] = None,
23
23
  version: Optional[int] = None,
24
+ protocol: Optional[str] = None,
24
25
  method_name: Optional[str] = None,
25
26
  tlp_span_kind: Optional[ObserveSpanKindValues] = ObserveSpanKindValues.TASK,
26
27
  ) -> Callable[[F], F]:
@@ -29,6 +30,7 @@ def task(
29
30
  name=name,
30
31
  description=description,
31
32
  version=version,
33
+ protocol=protocol,
32
34
  tlp_span_kind=tlp_span_kind,
33
35
  )
34
36
  else:
@@ -36,6 +38,7 @@ def task(
36
38
  name=name,
37
39
  description=description,
38
40
  version=version,
41
+ protocol=protocol,
39
42
  method_name=method_name,
40
43
  tlp_span_kind=tlp_span_kind,
41
44
  )
@@ -45,6 +48,7 @@ def workflow(
45
48
  name: Optional[str] = None,
46
49
  description: Optional[str] = None,
47
50
  version: Optional[int] = None,
51
+ protocol: Optional[str] = None,
48
52
  method_name: Optional[str] = None,
49
53
  tlp_span_kind: Optional[
50
54
  Union[ObserveSpanKindValues, str]
@@ -57,6 +61,7 @@ def workflow(
57
61
  name=name,
58
62
  description=description,
59
63
  version=version,
64
+ protocol=protocol,
60
65
  method_name=method_name,
61
66
  tlp_span_kind=tlp_span_kind,
62
67
  )(target)
@@ -66,6 +71,7 @@ def workflow(
66
71
  name=name,
67
72
  description=description,
68
73
  version=version,
74
+ protocol=protocol,
69
75
  tlp_span_kind=tlp_span_kind,
70
76
  )(target)
71
77
 
@@ -77,14 +83,18 @@ def graph(
77
83
  description: Optional[str] = None,
78
84
  version: Optional[int] = None,
79
85
  method_name: Optional[str] = None,
86
+ protocol: Optional[str] = None,
80
87
  ) -> Callable[[F], F]:
81
88
  if method_name is None:
82
- return entity_method(name=name, version=version, tlp_span_kind="graph")
89
+ return entity_method(
90
+ name=name, version=version, protocol=protocol, tlp_span_kind="graph"
91
+ )
83
92
  else:
84
93
  return entity_class(
85
94
  name=name,
86
95
  version=version,
87
96
  method_name=method_name,
97
+ protocol=protocol,
88
98
  tlp_span_kind="graph",
89
99
  )
90
100
 
@@ -93,12 +103,14 @@ def agent(
93
103
  name: Optional[str] = None,
94
104
  description: Optional[str] = None,
95
105
  version: Optional[int] = None,
106
+ protocol: Optional[str] = None,
96
107
  method_name: Optional[str] = None,
97
108
  ) -> Callable[[F], F]:
98
109
  return workflow(
99
110
  name=name,
100
111
  description=description,
101
112
  version=version,
113
+ protocol=protocol,
102
114
  method_name=method_name,
103
115
  tlp_span_kind=ObserveSpanKindValues.AGENT,
104
116
  )
@@ -7,7 +7,7 @@ import traceback
7
7
  from functools import wraps
8
8
  import os
9
9
  import types
10
- from typing import Optional, TypeVar, Callable, Awaitable, Any, cast, Union
10
+ from typing import Optional, TypeVar, Callable, Awaitable, Any, Union
11
11
  import inspect
12
12
 
13
13
  from ioa_observe.sdk.decorators.helpers import (
@@ -285,13 +285,23 @@ def _cleanup_span(span, ctx_token):
285
285
  context_api.detach(ctx_token)
286
286
 
287
287
 
288
+ def _unwrap_structured_tool(fn):
289
+ # Unwraps StructuredTool or similar wrappers to get the underlying function
290
+ if hasattr(fn, "func") and callable(fn.func):
291
+ return fn.func
292
+ return fn
293
+
294
+
288
295
  def entity_method(
289
296
  name: Optional[str] = None,
290
297
  description: Optional[str] = None,
291
298
  version: Optional[int] = None,
299
+ protocol: Optional[str] = None,
292
300
  tlp_span_kind: Optional[ObserveSpanKindValues] = ObserveSpanKindValues.TASK,
293
301
  ) -> Callable[[F], F]:
294
302
  def decorate(fn: F) -> F:
303
+ # Unwrap StructuredTool if present
304
+ fn = _unwrap_structured_tool(fn)
295
305
  is_async = _is_async_method(fn)
296
306
  entity_name = name or _get_original_function_name(fn)
297
307
  if is_async:
@@ -367,7 +377,7 @@ def entity_method(
367
377
  agent_recovery_tracker.record_agent_recovery(
368
378
  entity_name
369
379
  )
370
- _handle_graph_response(span, res, tlp_span_kind)
380
+ _handle_graph_response(span, res, protocol, tlp_span_kind)
371
381
  # span will be ended in the generator
372
382
  if isinstance(res, types.GeneratorType):
373
383
  return _handle_generator(span, res)
@@ -413,7 +423,7 @@ def entity_method(
413
423
  _cleanup_span(span, ctx_token)
414
424
  return res
415
425
 
416
- return cast(F, async_wrap)
426
+ decorated = async_wrap
417
427
  else:
418
428
 
419
429
  @wraps(fn)
@@ -477,7 +487,7 @@ def entity_method(
477
487
  agent_recovery_tracker.record_agent_recovery(
478
488
  entity_name
479
489
  )
480
- _handle_graph_response(span, res, tlp_span_kind)
490
+ _handle_graph_response(span, res, protocol, tlp_span_kind)
481
491
 
482
492
  # span will be ended in the generator
483
493
  if isinstance(res, types.GeneratorType):
@@ -524,7 +534,12 @@ def entity_method(
524
534
  _cleanup_span(span, ctx_token)
525
535
  return res
526
536
 
527
- return cast(F, sync_wrap)
537
+ decorated = sync_wrap
538
+ # # If the original fn was a StructuredTool, re-wrap
539
+ if hasattr(fn, "func") and callable(fn.func):
540
+ fn.func = decorated
541
+ return fn
542
+ return decorated
528
543
 
529
544
  return decorate
530
545
 
@@ -533,6 +548,7 @@ def entity_class(
533
548
  name: Optional[str],
534
549
  description: Optional[str],
535
550
  version: Optional[int],
551
+ protocol: Optional[str],
536
552
  method_name: Optional[str],
537
553
  tlp_span_kind: Optional[ObserveSpanKindValues] = ObserveSpanKindValues.TASK,
538
554
  ):
@@ -577,16 +593,18 @@ def entity_class(
577
593
  if hasattr(cls, method_to_wrap):
578
594
  original_method = getattr(cls, method_to_wrap)
579
595
  # Only wrap actual functions defined in this class
580
- if inspect.isfunction(original_method):
596
+ unwrapped_method = _unwrap_structured_tool(original_method)
597
+ if inspect.isfunction(unwrapped_method):
581
598
  try:
582
599
  # Verify the method has a proper signature
583
- sig = inspect.signature(original_method)
600
+ sig = inspect.signature(unwrapped_method)
584
601
  wrapped_method = entity_method(
585
602
  name=f"{task_name}.{method_to_wrap}",
586
603
  description=description,
587
604
  version=version,
605
+ protocol=protocol,
588
606
  tlp_span_kind=tlp_span_kind,
589
- )(original_method)
607
+ )(unwrapped_method)
590
608
  # Set the wrapped method on the class
591
609
  setattr(cls, method_to_wrap, wrapped_method)
592
610
  except Exception:
@@ -646,15 +664,17 @@ def _handle_execution_result(span, success):
646
664
  return
647
665
 
648
666
 
649
- def _handle_graph_response(span, res, tlp_span_kind):
667
+ def _handle_graph_response(span, res, protocol, tlp_span_kind):
650
668
  if tlp_span_kind == "graph":
669
+ if protocol:
670
+ protocol = protocol.upper()
671
+ span.set_attribute("gen_ai.ioa.graph.protocol", protocol)
651
672
  # Check if the response is a Llama Index Workflow object
652
673
  graph = determine_workflow_type(res)
653
674
  if graph is not None:
654
675
  # Convert the graph to JSON string
655
676
  graph_json = json.dumps(graph, indent=2)
656
677
  span.set_attribute("gen_ai.ioa.graph", graph_json)
657
-
658
678
  # get graph dynamism
659
679
  dynamism = topology_dynamism(graph)
660
680
  span.set_attribute("gen_ai.ioa.graph_dynamism", dynamism)
@@ -13,7 +13,7 @@ from llama_index.core.workflow.utils import (
13
13
  )
14
14
 
15
15
 
16
- def _serialize_object(obj, max_depth=5, current_depth=0):
16
+ def _serialize_object(obj, max_depth=3, current_depth=0):
17
17
  """
18
18
  Intelligently serialize an object to a more meaningful representation
19
19
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ioa-observe-sdk
3
- Version: 1.0.13
3
+ Version: 1.0.15
4
4
  Summary: IOA Observability SDK
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -15,17 +15,28 @@ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.33.1
15
15
  Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.33.1
16
16
  Requires-Dist: opentelemetry-instrumentation
17
17
  Requires-Dist: opentelemetry-instrumentation-logging==0.54b1
18
- Requires-Dist: opentelemetry-instrumentation-openai==0.40.8
19
- Requires-Dist: opentelemetry-instrumentation-llamaindex==0.40.8
20
- Requires-Dist: opentelemetry-instrumentation-ollama==0.40.8
21
- Requires-Dist: opentelemetry-instrumentation-anthropic==0.40.8
22
- Requires-Dist: opentelemetry-instrumentation-langchain==0.40.8
23
- Requires-Dist: opentelemetry-instrumentation-threading==00.54b1
18
+ Requires-Dist: opentelemetry-instrumentation-openai==0.43.1
19
+ Requires-Dist: opentelemetry-instrumentation-llamaindex==0.43.1
20
+ Requires-Dist: opentelemetry-instrumentation-ollama==0.43.1
21
+ Requires-Dist: opentelemetry-instrumentation-anthropic==0.43.1
22
+ Requires-Dist: opentelemetry-instrumentation-langchain==0.43.1
23
+ Requires-Dist: opentelemetry-instrumentation-bedrock==0.43.1
24
+ Requires-Dist: opentelemetry-instrumentation-cohere==0.43.1
25
+ Requires-Dist: opentelemetry-instrumentation-crewai==0.43.1
26
+ Requires-Dist: opentelemetry-instrumentation-google-generativeai==0.43.1
27
+ Requires-Dist: opentelemetry-instrumentation-groq==0.43.1
28
+ Requires-Dist: opentelemetry-instrumentation-mistralai==0.43.1
29
+ Requires-Dist: opentelemetry-instrumentation-requests==0.54b1
30
+ Requires-Dist: opentelemetry-instrumentation-sagemaker==0.43.1
31
+ Requires-Dist: opentelemetry-instrumentation-threading==0.54b1
32
+ Requires-Dist: opentelemetry-instrumentation-together==0.43.1
33
+ Requires-Dist: opentelemetry-instrumentation-transformers==0.43.1
24
34
  Requires-Dist: opentelemetry-instrumentation-urllib3==0.54b1
35
+ Requires-Dist: opentelemetry-instrumentation-vertexai==0.43.1
25
36
  Requires-Dist: opentelemetry-proto==1.33.1
26
37
  Requires-Dist: opentelemetry-sdk==1.33.1
27
38
  Requires-Dist: opentelemetry-semantic-conventions==0.54b1
28
- Requires-Dist: opentelemetry-semantic-conventions-ai==0.4.9
39
+ Requires-Dist: opentelemetry-semantic-conventions-ai>=0.4.11
29
40
  Requires-Dist: opentelemetry-util-http==0.54b1
30
41
  Requires-Dist: langgraph>=0.3.2
31
42
  Requires-Dist: langchain>=0.3.19
@@ -9,10 +9,10 @@ ioa_observe/sdk/client/http.py,sha256=LdLYSQPFIhKN5BTB-N78jLO7ITl7jGjA0-qpewEIvO
9
9
  ioa_observe/sdk/config/__init__.py,sha256=8aVNaw0yRNLFPxlf97iOZLlJVcV81ivSDnudH2m1OIo,572
10
10
  ioa_observe/sdk/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  ioa_observe/sdk/connectors/slim.py,sha256=NwbKEV7d5NIOqmG8zKqtgGigSJl7kf3QJ65z2gxpsY8,8498
12
- ioa_observe/sdk/decorators/__init__.py,sha256=Lv5EbouBazvWaYB0N82v26pqKtj2FAqlwfLKEh5e8Q0,3251
13
- ioa_observe/sdk/decorators/base.py,sha256=wdllPcsb_vtq8Kbu1oF7eg2Z5e-Rgv8XUu1Shsk1Fp4,29395
12
+ ioa_observe/sdk/decorators/__init__.py,sha256=c8gzCG-CASNI61RiTpNiTvMfguWvn4zc25fhBBgbHFA,3626
13
+ ioa_observe/sdk/decorators/base.py,sha256=KbSxFUTP_qpZA0gzt_xe4pFTu9SLpAo1MbHskQ3BQ9A,30208
14
14
  ioa_observe/sdk/decorators/helpers.py,sha256=I9HXMBivkZpGDtPe9Ad_UU35p_m_wEPate4r_fU0oOA,2705
15
- ioa_observe/sdk/decorators/util.py,sha256=v0dBY-ynyiLFHwQSteBfoCZ-rxwPUTgfczokKlevSKM,30068
15
+ ioa_observe/sdk/decorators/util.py,sha256=IebvH9gwZN1en3LblYJUh4bAV2STl6xmp8WpZzBDH2g,30068
16
16
  ioa_observe/sdk/instrumentations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  ioa_observe/sdk/instrumentations/a2a.py,sha256=ov_9ckkymf_qFXG0iXVWfxlW-3kFcP-knrM_t-Cf72w,4414
18
18
  ioa_observe/sdk/instrumentations/slim.py,sha256=J5e6XeshH55xXaUiT9_j4R_n6VQELzBjgRAU-AgZGOg,11435
@@ -39,8 +39,8 @@ ioa_observe/sdk/utils/const.py,sha256=GwbHakKPjBL4wLqAVkDrSoKB-8p18EUrbaqPuRuV_x
39
39
  ioa_observe/sdk/utils/in_memory_span_exporter.py,sha256=H_4TRaThMO1H6vUQ0OpQvzJk_fZH0OOsRAM1iZQXsR8,2112
40
40
  ioa_observe/sdk/utils/json_encoder.py,sha256=g4NQ0tTqgWssY6I1D7r4zo0G6PiUo61jhofTAw5-jno,639
41
41
  ioa_observe/sdk/utils/package_check.py,sha256=1d1MjxhwoEZIx9dumirT2pRsEWgn-m-SI4npDeEalew,576
42
- ioa_observe_sdk-1.0.13.dist-info/licenses/LICENSE.md,sha256=55VjUfgjWOS4vv3Cf55gfq-RxjPgRIO2vlgYPUuC5lA,11362
43
- ioa_observe_sdk-1.0.13.dist-info/METADATA,sha256=h0RjY4epTI6SNW15L-Lxlv0OjN9L0UrfQyQJYGk6lCg,6109
44
- ioa_observe_sdk-1.0.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- ioa_observe_sdk-1.0.13.dist-info/top_level.txt,sha256=Yt-6Y1olZEDqCs2REeqI30WjYx0pLGQSVqzYmDd67N8,12
46
- ioa_observe_sdk-1.0.13.dist-info/RECORD,,
42
+ ioa_observe_sdk-1.0.15.dist-info/licenses/LICENSE.md,sha256=55VjUfgjWOS4vv3Cf55gfq-RxjPgRIO2vlgYPUuC5lA,11362
43
+ ioa_observe_sdk-1.0.15.dist-info/METADATA,sha256=WwtaLg1AX6BXTs0ar7ru1rJ2GRKfoFMMpv8raR1FNLM,6799
44
+ ioa_observe_sdk-1.0.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ ioa_observe_sdk-1.0.15.dist-info/top_level.txt,sha256=Yt-6Y1olZEDqCs2REeqI30WjYx0pLGQSVqzYmDd67N8,12
46
+ ioa_observe_sdk-1.0.15.dist-info/RECORD,,