ioa-observe-sdk 1.0.10__py3-none-any.whl → 1.0.12__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.
@@ -43,7 +43,6 @@ from ioa_observe.sdk.utils.const import (
43
43
  from ioa_observe.sdk.utils.json_encoder import JSONEncoder
44
44
  from ioa_observe.sdk.metrics.agent import topology_dynamism, determinism_score
45
45
 
46
-
47
46
  P = ParamSpec("P")
48
47
 
49
48
  R = TypeVar("R")
@@ -554,30 +553,53 @@ def entity_class(
554
553
  # Specific method specified - existing behavior
555
554
  methods_to_wrap = [method_name]
556
555
  else:
557
- # No method specified - wrap all public methods
556
+ # No method specified - wrap all public methods defined in this class
558
557
  for attr_name in dir(cls):
559
558
  if (
560
559
  not attr_name.startswith("_") # Skip private/built-in methods
561
560
  and attr_name != "mro" # Skip class method
562
561
  and hasattr(cls, attr_name)
563
- and callable(getattr(cls, attr_name))
564
- and not isinstance(
565
- getattr(cls, attr_name), (classmethod, staticmethod, property)
566
- )
567
562
  ):
568
- methods_to_wrap.append(attr_name)
563
+ attr = getattr(cls, attr_name)
564
+ # Only wrap functions defined in this class (not inherited methods or built-ins)
565
+ if (
566
+ inspect.isfunction(attr) # Functions defined in the class
567
+ and not isinstance(attr, (classmethod, staticmethod, property))
568
+ and hasattr(attr, "__qualname__") # Has qualname attribute
569
+ and attr.__qualname__.startswith(
570
+ cls.__name__ + "."
571
+ ) # Defined in this class
572
+ ):
573
+ # Additional check: ensure the function has a proper signature with 'self' parameter
574
+ try:
575
+ sig = inspect.signature(attr)
576
+ params = list(sig.parameters.keys())
577
+ if params and params[0] == "self":
578
+ methods_to_wrap.append(attr_name)
579
+ except (ValueError, TypeError):
580
+ # Skip methods that can't be inspected
581
+ continue
569
582
 
570
583
  # Wrap all detected methods
571
584
  for method_to_wrap in methods_to_wrap:
572
585
  if hasattr(cls, method_to_wrap):
573
- method = getattr(cls, method_to_wrap)
574
- wrapped_method = entity_method(
575
- name=f"{task_name}.{method_to_wrap}",
576
- description=description,
577
- version=version,
578
- tlp_span_kind=tlp_span_kind,
579
- )(method)
580
- setattr(cls, method_to_wrap, wrapped_method)
586
+ original_method = getattr(cls, method_to_wrap)
587
+ # Only wrap actual functions defined in this class
588
+ if inspect.isfunction(original_method):
589
+ try:
590
+ # Verify the method has a proper signature
591
+ sig = inspect.signature(original_method)
592
+ wrapped_method = entity_method(
593
+ name=f"{task_name}.{method_to_wrap}",
594
+ description=description,
595
+ version=version,
596
+ tlp_span_kind=tlp_span_kind,
597
+ )(original_method)
598
+ # Set the wrapped method on the class
599
+ setattr(cls, method_to_wrap, wrapped_method)
600
+ except Exception:
601
+ # Don't wrap methods that can't be properly decorated
602
+ continue
581
603
 
582
604
  return cls
583
605
 
@@ -66,26 +66,71 @@ class SLIMInstrumentor(BaseInstrumentor):
66
66
  if traceparent and session_id:
67
67
  baggage.set_baggage(f"execution.{traceparent}", session_id)
68
68
 
69
- # Process message payload
69
+ # Process message payload and preserve original structure
70
70
  if isinstance(message, bytes):
71
71
  try:
72
72
  decoded_message = message.decode("utf-8")
73
73
  try:
74
- json.loads(decoded_message)
75
- payload = decoded_message
74
+ # If it's already a JSON structure, preserve it
75
+ original_message = json.loads(decoded_message)
76
+ if isinstance(original_message, dict):
77
+ # Preserve all original fields and merge/update headers
78
+ wrapped_message = original_message.copy()
79
+ existing_headers = wrapped_message.get("headers", {})
80
+ existing_headers.update(headers)
81
+ wrapped_message["headers"] = existing_headers
82
+ else:
83
+ # If it's not a dict, wrap it as payload
84
+ wrapped_message = {
85
+ "headers": headers,
86
+ "payload": original_message,
87
+ }
76
88
  except json.JSONDecodeError:
77
- payload = decoded_message
89
+ # If it's not JSON, treat as raw payload
90
+ wrapped_message = {
91
+ "headers": headers,
92
+ "payload": decoded_message,
93
+ }
78
94
  except UnicodeDecodeError:
79
- payload = base64.b64encode(message).decode("utf-8")
95
+ # If it can't be decoded, base64 encode it
96
+ wrapped_message = {
97
+ "headers": headers,
98
+ "payload": base64.b64encode(message).decode("utf-8"),
99
+ }
80
100
  elif isinstance(message, str):
81
- payload = message
101
+ try:
102
+ # Try to parse as JSON first
103
+ original_message = json.loads(message)
104
+ if isinstance(original_message, dict):
105
+ # Preserve all original fields and merge/update headers
106
+ wrapped_message = original_message.copy()
107
+ existing_headers = wrapped_message.get("headers", {})
108
+ existing_headers.update(headers)
109
+ wrapped_message["headers"] = existing_headers
110
+ else:
111
+ # If it's not a dict, wrap it as payload
112
+ wrapped_message = {
113
+ "headers": headers,
114
+ "payload": original_message,
115
+ }
116
+ except json.JSONDecodeError:
117
+ # If it's not JSON, treat as raw payload
118
+ wrapped_message = {
119
+ "headers": headers,
120
+ "payload": message,
121
+ }
122
+ elif isinstance(message, dict):
123
+ # If it's already a dict, preserve all fields and merge headers
124
+ wrapped_message = message.copy()
125
+ existing_headers = wrapped_message.get("headers", {})
126
+ existing_headers.update(headers)
127
+ wrapped_message["headers"] = existing_headers
82
128
  else:
83
- payload = json.dumps(message)
84
-
85
- wrapped_message = {
86
- "headers": headers,
87
- "payload": payload,
88
- }
129
+ # For other types, convert to JSON and wrap as payload
130
+ wrapped_message = {
131
+ "headers": headers,
132
+ "payload": json.dumps(message),
133
+ }
89
134
 
90
135
  message_to_send = json.dumps(wrapped_message).encode("utf-8")
91
136
 
@@ -152,20 +197,39 @@ class SLIMInstrumentor(BaseInstrumentor):
152
197
  session_id = stored_session_id
153
198
  set_session_id(session_id, traceparent=traceparent)
154
199
 
155
- # Process payload
156
- payload = message_dict.get("payload", raw_message)
157
- if isinstance(payload, str):
158
- try:
159
- payload_dict = json.loads(payload)
160
- return recv_session, json.dumps(payload_dict).encode("utf-8")
161
- except json.JSONDecodeError:
162
- return recv_session, payload.encode("utf-8") if isinstance(
163
- payload, str
164
- ) else payload
165
-
166
- return recv_session, json.dumps(payload).encode("utf-8") if isinstance(
167
- payload, (dict, list)
168
- ) else payload
200
+ # Process the complete message structure
201
+ # Remove tracing headers before returning the message
202
+ message_to_return = message_dict.copy()
203
+ if "headers" in message_to_return:
204
+ headers_copy = message_to_return["headers"].copy()
205
+ # Remove tracing-specific headers but keep other headers
206
+ headers_copy.pop("traceparent", None)
207
+ headers_copy.pop("session_id", None)
208
+ if headers_copy:
209
+ message_to_return["headers"] = headers_copy
210
+ else:
211
+ message_to_return.pop("headers", None)
212
+
213
+ # If the message only contains a payload field and no other fields,
214
+ # return just the payload for backward compatibility
215
+ if len(message_to_return) == 1 and "payload" in message_to_return:
216
+ payload = message_to_return["payload"]
217
+ if isinstance(payload, str):
218
+ try:
219
+ payload_dict = json.loads(payload)
220
+ return recv_session, json.dumps(payload_dict).encode(
221
+ "utf-8"
222
+ )
223
+ except json.JSONDecodeError:
224
+ return recv_session, payload.encode("utf-8") if isinstance(
225
+ payload, str
226
+ ) else payload
227
+ return recv_session, json.dumps(payload).encode(
228
+ "utf-8"
229
+ ) if isinstance(payload, (dict, list)) else payload
230
+ else:
231
+ # Return the complete message structure with all original fields
232
+ return recv_session, json.dumps(message_to_return).encode("utf-8")
169
233
 
170
234
  except Exception as e:
171
235
  print(f"Error processing message: {e}")
@@ -1,38 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ioa-observe-sdk
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: IOA Observability SDK
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
7
7
  License-File: LICENSE.md
8
- Requires-Dist: aiohappyeyeballs>=2.4.8
9
- Requires-Dist: aiohttp>=3.11.18
10
- Requires-Dist: aiosignal>=1.3.2
11
- Requires-Dist: annotated-types>=0.7.0
12
- Requires-Dist: anyio>=4.8.0
13
- Requires-Dist: async-timeout>=4.0.3
14
- Requires-Dist: attrs>=25.1.0
15
- Requires-Dist: backoff>=2.2.1
16
- Requires-Dist: certifi>=2025.1.31
17
- Requires-Dist: charset-normalizer>=3.4.1
18
8
  Requires-Dist: colorama==0.4.6
19
- Requires-Dist: Deprecated>=1.2.18
20
- Requires-Dist: distro>=1.9.0
21
- Requires-Dist: exceptiongroup>=1.2.2
22
- Requires-Dist: frozenlist>=1.5.0
23
- Requires-Dist: googleapis-common-protos>=1.69.0
24
- Requires-Dist: grpcio>=1.70.0
25
- Requires-Dist: h11>=0.16.0
26
- Requires-Dist: httpcore>=1.0.9
27
- Requires-Dist: httpx>=0.28.1
28
- Requires-Dist: idna>=3.10
29
- Requires-Dist: importlib_metadata>=8.5.0
30
- Requires-Dist: Jinja2>=3.1.6
31
- Requires-Dist: jiter>=0.8.2
32
- Requires-Dist: MarkupSafe>=3.0.2
33
- Requires-Dist: monotonic>=1.6
34
- Requires-Dist: multidict>=6.1.0
35
- Requires-Dist: openai>=1.75.0
9
+ Requires-Dist: requests>=2.32.3
36
10
  Requires-Dist: opentelemetry-api==1.33.1
37
11
  Requires-Dist: opentelemetry-distro
38
12
  Requires-Dist: opentelemetry-exporter-otlp==1.33.1
@@ -44,6 +18,7 @@ Requires-Dist: opentelemetry-instrumentation-logging==0.54b1
44
18
  Requires-Dist: opentelemetry-instrumentation-openai==0.40.8
45
19
  Requires-Dist: opentelemetry-instrumentation-llamaindex==0.40.8
46
20
  Requires-Dist: opentelemetry-instrumentation-ollama==0.40.8
21
+ Requires-Dist: opentelemetry-instrumentation-anthropic==0.40.8
47
22
  Requires-Dist: opentelemetry-instrumentation-langchain==0.40.8
48
23
  Requires-Dist: opentelemetry-instrumentation-threading==00.54b1
49
24
  Requires-Dist: opentelemetry-instrumentation-urllib3==0.54b1
@@ -52,33 +27,10 @@ Requires-Dist: opentelemetry-sdk==1.33.1
52
27
  Requires-Dist: opentelemetry-semantic-conventions==0.54b1
53
28
  Requires-Dist: opentelemetry-semantic-conventions-ai==0.4.9
54
29
  Requires-Dist: opentelemetry-util-http==0.54b1
55
- Requires-Dist: packaging>=24.2
56
- Requires-Dist: propcache>=0.3.0
57
- Requires-Dist: protobuf>=5.29.3
58
- Requires-Dist: pydantic>=2.10.6
59
- Requires-Dist: pydantic_core>=2.27.2
60
- Requires-Dist: python-dateutil>=2.9.0.post0
61
- Requires-Dist: regex==2024.11.6
62
- Requires-Dist: requests>=2.32.3
63
- Requires-Dist: six>=1.17.0
64
- Requires-Dist: sniffio>=1.3.1
65
- Requires-Dist: tenacity>=9.0.0
66
- Requires-Dist: tiktoken>=0.9.0
67
- Requires-Dist: tqdm>=4.67.1
68
- Requires-Dist: typing_extensions>=4.12.2
69
- Requires-Dist: urllib3>=2.3.0
70
- Requires-Dist: wrapt>=1.17.2
71
- Requires-Dist: yarl>=1.18.3
72
- Requires-Dist: zipp>=3.21.0
73
30
  Requires-Dist: langgraph>=0.3.2
74
31
  Requires-Dist: langchain>=0.3.19
75
32
  Requires-Dist: langchain-openai>=0.3.8
76
- Requires-Dist: langchain-community>=0.3.25
77
33
  Requires-Dist: llama-index>=0.12.34
78
- Requires-Dist: opentelemetry-instrumentation-requests
79
- Requires-Dist: opentelemetry-instrumentation-transformers>=0.40.8
80
- Requires-Dist: opentelemetry-instrumentation-crewai>=0.40.8
81
- Requires-Dist: llama-index-utils-workflow>=0.3.1
82
34
  Requires-Dist: pytest
83
35
  Requires-Dist: pytest-vcr
84
36
  Dynamic: license-file
@@ -10,11 +10,11 @@ ioa_observe/sdk/config/__init__.py,sha256=8aVNaw0yRNLFPxlf97iOZLlJVcV81ivSDnudH2
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
12
  ioa_observe/sdk/decorators/__init__.py,sha256=Lv5EbouBazvWaYB0N82v26pqKtj2FAqlwfLKEh5e8Q0,3251
13
- ioa_observe/sdk/decorators/base.py,sha256=vZuF9bsaMhH0BAJjPvmPA-cvdgaXucRuSvGHhvc_8tc,28483
13
+ ioa_observe/sdk/decorators/base.py,sha256=kR_0KWMMbOdJ_t9m5EZ9ZUj3pmKWEgkj0-E1F3c-nIE,29969
14
14
  ioa_observe/sdk/decorators/util.py,sha256=WMkzmwD7Js0g1BbId9_qR4pwhnaIJdW588zVc5dpqdQ,25399
15
15
  ioa_observe/sdk/instrumentations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  ioa_observe/sdk/instrumentations/a2a.py,sha256=ov_9ckkymf_qFXG0iXVWfxlW-3kFcP-knrM_t-Cf72w,4414
17
- ioa_observe/sdk/instrumentations/slim.py,sha256=w2-1JRB-I05bqH_Y4-98XMOh0x7xgAJWUYUBpe2alXQ,7656
17
+ ioa_observe/sdk/instrumentations/slim.py,sha256=J5e6XeshH55xXaUiT9_j4R_n6VQELzBjgRAU-AgZGOg,11435
18
18
  ioa_observe/sdk/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  ioa_observe/sdk/logging/logging.py,sha256=HZxW9s8Due7jgiNkdI38cIjv5rC9D-Flta3RQMOnpow,2891
20
20
  ioa_observe/sdk/metrics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -38,8 +38,8 @@ ioa_observe/sdk/utils/const.py,sha256=GwbHakKPjBL4wLqAVkDrSoKB-8p18EUrbaqPuRuV_x
38
38
  ioa_observe/sdk/utils/in_memory_span_exporter.py,sha256=H_4TRaThMO1H6vUQ0OpQvzJk_fZH0OOsRAM1iZQXsR8,2112
39
39
  ioa_observe/sdk/utils/json_encoder.py,sha256=g4NQ0tTqgWssY6I1D7r4zo0G6PiUo61jhofTAw5-jno,639
40
40
  ioa_observe/sdk/utils/package_check.py,sha256=1d1MjxhwoEZIx9dumirT2pRsEWgn-m-SI4npDeEalew,576
41
- ioa_observe_sdk-1.0.10.dist-info/licenses/LICENSE.md,sha256=55VjUfgjWOS4vv3Cf55gfq-RxjPgRIO2vlgYPUuC5lA,11362
42
- ioa_observe_sdk-1.0.10.dist-info/METADATA,sha256=eNDXQNsig6-m56PqwvFuYH6XUtYG8konoqFk2UUHW9w,7747
43
- ioa_observe_sdk-1.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
- ioa_observe_sdk-1.0.10.dist-info/top_level.txt,sha256=Yt-6Y1olZEDqCs2REeqI30WjYx0pLGQSVqzYmDd67N8,12
45
- ioa_observe_sdk-1.0.10.dist-info/RECORD,,
41
+ ioa_observe_sdk-1.0.12.dist-info/licenses/LICENSE.md,sha256=55VjUfgjWOS4vv3Cf55gfq-RxjPgRIO2vlgYPUuC5lA,11362
42
+ ioa_observe_sdk-1.0.12.dist-info/METADATA,sha256=3owAgvI_xgARwMohc3ticBRqKwju2w-poBOu1SILHC4,6109
43
+ ioa_observe_sdk-1.0.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ ioa_observe_sdk-1.0.12.dist-info/top_level.txt,sha256=Yt-6Y1olZEDqCs2REeqI30WjYx0pLGQSVqzYmDd67N8,12
45
+ ioa_observe_sdk-1.0.12.dist-info/RECORD,,