monocle-apptrace 0.5.3__py3-none-any.whl → 0.6.6__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.

Potentially problematic release.


This version of monocle-apptrace might be problematic. Click here for more details.

Files changed (56) hide show
  1. monocle_apptrace/exporters/file_exporter.py +7 -1
  2. monocle_apptrace/instrumentation/common/constants.py +8 -0
  3. monocle_apptrace/instrumentation/common/instrumentor.py +1 -1
  4. monocle_apptrace/instrumentation/common/span_handler.py +75 -24
  5. monocle_apptrace/instrumentation/common/utils.py +63 -6
  6. monocle_apptrace/instrumentation/common/wrapper.py +111 -42
  7. monocle_apptrace/instrumentation/common/wrapper_method.py +6 -2
  8. monocle_apptrace/instrumentation/metamodel/a2a/methods.py +1 -1
  9. monocle_apptrace/instrumentation/metamodel/adk/_helper.py +7 -4
  10. monocle_apptrace/instrumentation/metamodel/adk/entities/agent.py +6 -1
  11. monocle_apptrace/instrumentation/metamodel/agents/_helper.py +8 -8
  12. monocle_apptrace/instrumentation/metamodel/agents/entities/inference.py +9 -2
  13. monocle_apptrace/instrumentation/metamodel/aiohttp/_helper.py +1 -1
  14. monocle_apptrace/instrumentation/metamodel/anthropic/entities/inference.py +1 -4
  15. monocle_apptrace/instrumentation/metamodel/azfunc/_helper.py +1 -1
  16. monocle_apptrace/instrumentation/metamodel/botocore/_helper.py +5 -0
  17. monocle_apptrace/instrumentation/metamodel/botocore/entities/inference.py +4 -0
  18. monocle_apptrace/instrumentation/metamodel/fastapi/_helper.py +4 -4
  19. monocle_apptrace/instrumentation/metamodel/fastapi/methods.py +4 -4
  20. monocle_apptrace/instrumentation/metamodel/finish_types.py +32 -1
  21. monocle_apptrace/instrumentation/metamodel/flask/_helper.py +3 -3
  22. monocle_apptrace/instrumentation/metamodel/hugging_face/__init__.py +0 -0
  23. monocle_apptrace/instrumentation/metamodel/hugging_face/_helper.py +138 -0
  24. monocle_apptrace/instrumentation/metamodel/hugging_face/entities/__init__.py +0 -0
  25. monocle_apptrace/instrumentation/metamodel/hugging_face/entities/inference.py +94 -0
  26. monocle_apptrace/instrumentation/metamodel/hugging_face/methods.py +23 -0
  27. monocle_apptrace/instrumentation/metamodel/lambdafunc/_helper.py +1 -1
  28. monocle_apptrace/instrumentation/metamodel/langchain/entities/inference.py +1 -4
  29. monocle_apptrace/instrumentation/metamodel/langgraph/_helper.py +34 -8
  30. monocle_apptrace/instrumentation/metamodel/langgraph/entities/inference.py +8 -3
  31. monocle_apptrace/instrumentation/metamodel/langgraph/langgraph_processor.py +88 -19
  32. monocle_apptrace/instrumentation/metamodel/langgraph/methods.py +22 -6
  33. monocle_apptrace/instrumentation/metamodel/llamaindex/_helper.py +30 -10
  34. monocle_apptrace/instrumentation/metamodel/llamaindex/entities/agent.py +4 -3
  35. monocle_apptrace/instrumentation/metamodel/llamaindex/llamaindex_processor.py +15 -7
  36. monocle_apptrace/instrumentation/metamodel/llamaindex/methods.py +1 -8
  37. monocle_apptrace/instrumentation/metamodel/mcp/_helper.py +7 -6
  38. monocle_apptrace/instrumentation/metamodel/mistral/_helper.py +98 -49
  39. monocle_apptrace/instrumentation/metamodel/mistral/entities/inference.py +15 -9
  40. monocle_apptrace/instrumentation/metamodel/mistral/entities/retrieval.py +41 -0
  41. monocle_apptrace/instrumentation/metamodel/mistral/methods.py +10 -1
  42. monocle_apptrace/instrumentation/metamodel/openai/_helper.py +47 -7
  43. monocle_apptrace/instrumentation/metamodel/openai/entities/inference.py +20 -4
  44. monocle_apptrace/instrumentation/metamodel/openai/methods.py +1 -1
  45. monocle_apptrace/instrumentation/metamodel/strands/_helper.py +44 -0
  46. monocle_apptrace/instrumentation/metamodel/strands/entities/agent.py +179 -0
  47. monocle_apptrace/instrumentation/metamodel/strands/entities/tool.py +62 -0
  48. monocle_apptrace/instrumentation/metamodel/strands/methods.py +20 -0
  49. {monocle_apptrace-0.5.3.dist-info → monocle_apptrace-0.6.6.dist-info}/METADATA +23 -79
  50. {monocle_apptrace-0.5.3.dist-info → monocle_apptrace-0.6.6.dist-info}/RECORD +53 -46
  51. monocle_apptrace/README.md +0 -101
  52. monocle_apptrace/mcp_server.py +0 -94
  53. monocle_apptrace-0.5.3.dist-info/licenses/NOTICE +0 -4
  54. {monocle_apptrace-0.5.3.dist-info → monocle_apptrace-0.6.6.dist-info}/WHEEL +0 -0
  55. {monocle_apptrace-0.5.3.dist-info → monocle_apptrace-0.6.6.dist-info}/entry_points.txt +0 -0
  56. {monocle_apptrace-0.5.3.dist-info → monocle_apptrace-0.6.6.dist-info}/licenses/LICENSE +0 -0
@@ -1,28 +1,35 @@
1
1
  # pylint: disable=protected-access
2
+ import logging
3
+ import os
2
4
  from contextlib import contextmanager
3
5
  import os
4
- from typing import AsyncGenerator, Iterator, Optional
6
+ from typing import AsyncGenerator, Iterator
5
7
  import logging
6
8
  from opentelemetry.trace import Tracer
7
- from opentelemetry.trace.propagation import _SPAN_KEY, set_span_in_context, get_current_span
8
- from opentelemetry.trace import propagation
9
+ from opentelemetry.trace.propagation import set_span_in_context, get_current_span
9
10
  from opentelemetry.context import set_value, attach, detach, get_value
10
- from opentelemetry.context import create_key, get_value, set_value
11
- from opentelemetry.context.context import Context
12
11
  from opentelemetry.trace.span import INVALID_SPAN, Span
13
12
  from opentelemetry.trace.status import StatusCode
14
13
 
14
+ from monocle_apptrace.instrumentation.common.constants import (
15
+ ADD_NEW_WORKFLOW,
16
+ AGENTIC_SPANS,
17
+ WORKFLOW_TYPE_KEY,
18
+ )
19
+ from monocle_apptrace.instrumentation.common.scope_wrapper import monocle_trace_scope
15
20
  from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
16
21
  from monocle_apptrace.instrumentation.common.utils import (
22
+ get_current_monocle_span,
23
+ remove_scope,
24
+ set_monocle_span_in_context,
25
+ set_scope,
17
26
  set_scopes,
18
27
  with_tracer_wrapper,
19
28
  set_scope,
20
29
  remove_scope,
21
30
  get_current_monocle_span,
22
- set_monocle_span_in_context
31
+ set_monocle_span_in_context,
23
32
  )
24
- from monocle_apptrace.instrumentation.common.constants import WORKFLOW_TYPE_KEY, ADD_NEW_WORKFLOW, AGENTIC_SPANS
25
- from monocle_apptrace.instrumentation.common.scope_wrapper import monocle_trace_scope
26
33
 
27
34
  logger = logging.getLogger(__name__)
28
35
  ISOLATE_MONOCLE_SPANS = os.getenv("MONOCLE_ISOLATE_SPANS", "true").lower() == "true"
@@ -53,7 +60,9 @@ def post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_
53
60
  try:
54
61
  if parent_span == INVALID_SPAN:
55
62
  parent_span = None
56
- handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, return_value, span, parent_span, ex)
63
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, return_value, span, parent_span, ex,
64
+ is_post_exec=True)
65
+ return_value = SpanHandler.replace_placeholders_in_response(return_value, span)
57
66
  except Exception as e:
58
67
  logger.info(f"Warning: Error occurred in hydrate_span: {e}")
59
68
 
@@ -61,6 +70,7 @@ def post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_
61
70
  handler.post_task_processing(to_wrap, wrapped, instance, args, kwargs, return_value, ex, span, parent_span)
62
71
  except Exception as e:
63
72
  logger.info(f"Warning: Error occurred in post_task_processing: {e}")
73
+ return return_value
64
74
 
65
75
  def get_span_name(to_wrap, instance):
66
76
  if to_wrap.get("span_name"):
@@ -87,19 +97,32 @@ def monocle_wrapper_span_processor(tracer: Tracer, handler: SpanHandler, to_wrap
87
97
  span.end()
88
98
  else:
89
99
  ex:Exception = None
90
- to_wrap = get_wrapper_with_next_processor(to_wrap, handler, instance, args, kwargs)
100
+ to_wrap = get_wrapper_with_next_processor(to_wrap, handler, instance, span, parent_span, args, kwargs)
91
101
  if has_more_processors(to_wrap):
92
102
  try:
93
- return_value, span_status = monocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs)
103
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, None, span, parent_span, ex,
104
+ is_post_exec=False)
105
+ except Exception as e:
106
+ logger.info(f"Warning: Error occurred in hydrate_span pre_process_span: {e}")
107
+ try:
108
+ with monocle_trace_scope(get_builtin_scope_names(to_wrap)):
109
+ return_value, span_status = monocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs)
94
110
  except Exception as e:
95
111
  ex = e
96
112
  raise
97
113
  finally:
98
- post_process_span_internal(return_value)
114
+ return_value = post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_value, span, parent_span ,ex)
99
115
  else:
100
116
  try:
101
- with SpanHandler.workflow_type(to_wrap, span):
102
- return_value = wrapped(*args, **kwargs)
117
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, None, span, parent_span, ex,
118
+ is_post_exec=False)
119
+ except Exception as e:
120
+ logger.info(f"Warning: Error occurred in hydrate_span pre_process_span: {e}")
121
+ try:
122
+ skip_execution, return_value = SpanHandler.skip_execution(span)
123
+ if not skip_execution:
124
+ with SpanHandler.workflow_type(to_wrap, span):
125
+ return_value = wrapped(*args, **kwargs)
103
126
  except Exception as e:
104
127
  ex = e
105
128
  raise
@@ -108,10 +131,11 @@ def monocle_wrapper_span_processor(tracer: Tracer, handler: SpanHandler, to_wrap
108
131
  post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span, parent_span ,ex)
109
132
  if not auto_close_span:
110
133
  span.end()
134
+ return ret_val
111
135
  if ex is None and not auto_close_span and to_wrap.get("output_processor") and to_wrap.get("output_processor").get("response_processor"):
112
136
  to_wrap.get("output_processor").get("response_processor")(to_wrap, return_value, post_process_span_internal)
113
137
  else:
114
- post_process_span_internal(return_value)
138
+ return_value = post_process_span_internal(return_value)
115
139
  span_status = span.status
116
140
  return return_value, span_status
117
141
 
@@ -121,7 +145,9 @@ def monocle_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, inst
121
145
  token = None
122
146
  try:
123
147
  try:
124
- pre_trace_token = handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
148
+ pre_trace_token, alternate_to_wrapp = handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
149
+ if alternate_to_wrapp is not None:
150
+ to_wrap = alternate_to_wrapp
125
151
  except Exception as e:
126
152
  logger.info(f"Warning: Error occurred in pre_tracing: {e}")
127
153
  if to_wrap.get('skip_span', False) or handler.skip_span(to_wrap, wrapped, instance, args, kwargs):
@@ -160,31 +186,46 @@ async def amonocle_wrapper_span_processor(tracer: Tracer, handler: SpanHandler,
160
186
  span.end()
161
187
  else:
162
188
  ex:Exception = None
163
- to_wrap = get_wrapper_with_next_processor(to_wrap, handler, instance, args, kwargs)
189
+ to_wrap = get_wrapper_with_next_processor(to_wrap, handler, instance, span, parent_span,args, kwargs)
164
190
  if has_more_processors(to_wrap):
165
191
  try:
166
- return_value, span_status = await amonocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs)
192
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, None, span, parent_span, ex,
193
+ is_post_exec=False)
194
+ except Exception as e:
195
+ logger.info(f"Warning: Error occurred in hydrate_span pre_process_span: {e}")
196
+
197
+ try:
198
+ with monocle_trace_scope(get_builtin_scope_names(to_wrap)):
199
+ return_value, span_status = await amonocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs)
167
200
  except Exception as e:
168
201
  ex = e
169
202
  raise
170
203
  finally:
171
- post_process_span_internal(return_value)
204
+ return_value = post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_value, span, parent_span ,ex)
172
205
  else:
173
206
  try:
174
- with SpanHandler.workflow_type(to_wrap, span):
175
- return_value = await wrapped(*args, **kwargs)
207
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, None, span, parent_span, ex,
208
+ is_post_exec=False)
209
+ except Exception as e:
210
+ logger.info(f"Warning: Error occurred in hydrate_span pre_process_span: {e}")
211
+ try:
212
+ skip_execution, return_value = SpanHandler.skip_execution(span)
213
+ if not skip_execution:
214
+ with SpanHandler.workflow_type(to_wrap, span):
215
+ return_value = await wrapped(*args, **kwargs)
176
216
  except Exception as e:
177
217
  ex = e
178
218
  raise
179
219
  finally:
180
220
  def post_process_span_internal(ret_val):
181
- post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span, parent_span, ex)
221
+ ret_val = post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span, parent_span, ex)
182
222
  if not auto_close_span:
183
223
  span.end()
224
+ return ret_val
184
225
  if ex is None and not auto_close_span and to_wrap.get("output_processor") and to_wrap.get("output_processor").get("response_processor"):
185
226
  to_wrap.get("output_processor").get("response_processor")(to_wrap, return_value, post_process_span_internal)
186
227
  else:
187
- post_process_span_internal(return_value)
228
+ return_value = post_process_span_internal(return_value)
188
229
  span_status = span.status
189
230
  return return_value, span_status
190
231
 
@@ -208,35 +249,50 @@ async def amonocle_iter_wrapper_span_processor(tracer: Tracer, handler: SpanHand
208
249
  span.end()
209
250
  else:
210
251
  ex:Exception = None
211
- to_wrap = get_wrapper_with_next_processor(to_wrap, handler, instance, args, kwargs)
252
+ to_wrap = get_wrapper_with_next_processor(to_wrap, handler, span, parent_span, instance, args, kwargs)
212
253
  if has_more_processors(to_wrap):
213
254
  try:
214
- async for item in amonocle_iter_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs):
215
- last_item = item
216
- yield item
255
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, None, span, parent_span, ex,
256
+ is_post_exec=False)
257
+ except Exception as e:
258
+ logger.info(f"Warning: Error occurred in hydrate_span pre_process_span: {e}")
259
+ try:
260
+ with monocle_trace_scope(get_builtin_scope_names(to_wrap)):
261
+ async for item in amonocle_iter_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs):
262
+ last_item = item
263
+ yield item
217
264
  except Exception as e:
218
265
  ex = e
219
266
  raise
220
267
  finally:
221
- post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, last_item, span, parent_span, ex)
268
+ last_item = post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, last_item, span, parent_span, ex)
222
269
  else:
223
270
  try:
224
- with SpanHandler.workflow_type(to_wrap, span):
225
- async for item in wrapped(*args, **kwargs):
226
- last_item = item
227
- yield item
271
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, None, span, parent_span, ex,
272
+ is_post_exec=False)
273
+ except Exception as e:
274
+ logger.info(f"Warning: Error occurred in hydrate_span pre_process_span: {e}")
275
+ try:
276
+ skip_execution, last_item = SpanHandler.skip_execution(span)
277
+ if not skip_execution:
278
+ with SpanHandler.workflow_type(to_wrap, span):
279
+ async for item in wrapped(*args, **kwargs):
280
+ last_item = item
281
+ yield item
282
+ else:
283
+ yield last_item
228
284
  except Exception as e:
229
285
  ex = e
230
286
  raise
231
287
  finally:
232
288
  def post_process_span_internal(ret_val):
233
- post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span, parent_span, ex)
289
+ ret_val = post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span, parent_span, ex)
234
290
  if not auto_close_span:
235
291
  span.end()
236
292
  if ex is None and not auto_close_span and to_wrap.get("output_processor") and to_wrap.get("output_processor").get("response_processor"):
237
293
  to_wrap.get("output_processor").get("response_processor")(to_wrap, None, post_process_span_internal)
238
294
  else:
239
- post_process_span_internal(last_item)
295
+ last_item = post_process_span_internal(last_item)
240
296
  return
241
297
 
242
298
  async def amonocle_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
@@ -245,7 +301,9 @@ async def amonocle_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrappe
245
301
  pre_trace_token = None
246
302
  try:
247
303
  try:
248
- pre_trace_token = handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
304
+ pre_trace_token, alternate_to_wrapp = handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
305
+ if alternate_to_wrapp is not None:
306
+ to_wrap = alternate_to_wrapp
249
307
  except Exception as e:
250
308
  logger.info(f"Warning: Error occurred in pre_tracing: {e}")
251
309
  if to_wrap.get('skip_span', False) or handler.skip_span(to_wrap, wrapped, instance, args, kwargs):
@@ -271,7 +329,9 @@ async def amonocle_iter_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, w
271
329
  pre_trace_token = None
272
330
  try:
273
331
  try:
274
- pre_trace_token = handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
332
+ pre_trace_token, alternate_to_wrapp = handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
333
+ if alternate_to_wrapp is not None:
334
+ to_wrap = alternate_to_wrapp
275
335
  except Exception as e:
276
336
  logger.info(f"Warning: Error occurred in pre_tracing: {e}")
277
337
  if to_wrap.get('skip_span', False) or handler.skip_span(to_wrap, wrapped, instance, args, kwargs):
@@ -373,13 +433,14 @@ def evaluate_scope_values(args, kwargs, to_wrap, scope_values):
373
433
  @contextmanager
374
434
  def start_as_monocle_span(tracer: Tracer, name: str, auto_close_span: bool) -> Iterator["Span"]:
375
435
  """ Wrapper to OTEL start_as_current_span to isolate monocle and non monocle spans.
376
- This essentiall links monocle and non-monocle spans separately which is default behavior.
436
+ This essentially links monocle and non-monocle spans separately which is default behavior.
377
437
  It can be optionally overridden by setting the environment variable MONOCLE_ISOLATE_SPANS to false.
378
438
  """
379
439
  if not ISOLATE_MONOCLE_SPANS:
380
440
  # If not isolating, use the default start_as_current_span
381
441
  yield tracer.start_as_current_span(name, end_on_exit=auto_close_span)
382
442
  return
443
+
383
444
  original_span = get_current_span()
384
445
  monocle_span_token = attach(set_span_in_context(get_current_monocle_span()))
385
446
  with tracer.start_as_current_span(name, end_on_exit=auto_close_span) as span:
@@ -391,18 +452,26 @@ def start_as_monocle_span(tracer: Tracer, name: str, auto_close_span: bool) -> I
391
452
  detach(monocle_span_token)
392
453
 
393
454
  def get_builtin_scope_names(to_wrap) -> str:
394
- output_processor = to_wrap.get("output_processor", None)
395
- span_type = output_processor.get("type", None) if output_processor else None
455
+ output_processor = None
456
+ if "output_processor" in to_wrap:
457
+ output_processor = to_wrap.get("output_processor", None)
458
+ if "output_processor_list" in to_wrap:
459
+ for processor in to_wrap["output_processor_list"]:
460
+ if processor.get("type", None) in AGENTIC_SPANS:
461
+ output_processor = processor
462
+ break
463
+
464
+ span_type = output_processor.get("type", None) if output_processor and isinstance(output_processor, dict) else None
396
465
  if span_type and span_type in AGENTIC_SPANS:
397
466
  return span_type
398
467
  return None
399
468
 
400
- def get_wrapper_with_next_processor(to_wrap, handler, instance, args, kwargs):
469
+ def get_wrapper_with_next_processor(to_wrap, handler, instance, span, parent_span, args, kwargs):
401
470
  if has_more_processors(to_wrap):
402
471
  next_output_processor_list = to_wrap.get('output_processor_list',[]).copy()
403
472
  while len(next_output_processor_list) > 0:
404
473
  next_output_processor = next_output_processor_list.pop(0)
405
- if handler.should_skip(next_output_processor, instance, args, kwargs):
474
+ if handler.should_skip(next_output_processor, instance, span, parent_span, args, kwargs):
406
475
  next_output_processor = None
407
476
  else:
408
477
  break
@@ -412,4 +481,4 @@ def get_wrapper_with_next_processor(to_wrap, handler, instance, args, kwargs):
412
481
  return to_wrap
413
482
 
414
483
  def has_more_processors(to_wrap) -> bool:
415
- return len(to_wrap.get('output_processor_list', [])) > 0
484
+ return len(to_wrap.get('output_processor_list', [])) > 0
@@ -5,6 +5,7 @@ from monocle_apptrace.instrumentation.common.span_handler import SpanHandler, No
5
5
  from monocle_apptrace.instrumentation.metamodel.azureaiinference.methods import AZURE_AI_INFERENCE_METHODS
6
6
  from monocle_apptrace.instrumentation.metamodel.botocore.methods import BOTOCORE_METHODS
7
7
  from monocle_apptrace.instrumentation.metamodel.botocore.handlers.botocore_span_handler import BotoCoreSpanHandler
8
+ from monocle_apptrace.instrumentation.metamodel.hugging_face.methods import HUGGING_FACE_METHODS
8
9
  from monocle_apptrace.instrumentation.metamodel.langchain.methods import (
9
10
  LANGCHAIN_METHODS,
10
11
  )
@@ -38,6 +39,7 @@ from monocle_apptrace.instrumentation.metamodel.a2a.methods import A2A_CLIENT_ME
38
39
  from monocle_apptrace.instrumentation.metamodel.litellm.methods import LITELLM_METHODS
39
40
  from monocle_apptrace.instrumentation.metamodel.adk.methods import ADK_METHODS
40
41
  from monocle_apptrace.instrumentation.metamodel.mistral.methods import MISTRAL_METHODS
42
+ from monocle_apptrace.instrumentation.metamodel.strands.methods import STRAND_METHODS
41
43
 
42
44
  class WrapperMethod:
43
45
  def __init__(
@@ -109,7 +111,9 @@ DEFAULT_METHODS_LIST = (
109
111
  A2A_CLIENT_METHODS +
110
112
  LITELLM_METHODS +
111
113
  ADK_METHODS +
112
- MISTRAL_METHODS
114
+ MISTRAL_METHODS +
115
+ HUGGING_FACE_METHODS +
116
+ STRAND_METHODS
113
117
  )
114
118
 
115
119
  MONOCLE_SPAN_HANDLERS: Dict[str, SpanHandler] = {
@@ -131,5 +135,5 @@ MONOCLE_SPAN_HANDLERS: Dict[str, SpanHandler] = {
131
135
  "llamaindex_tool_handler": LlamaIndexToolHandler(),
132
136
  "llamaindex_agent_handler": LlamaIndexAgentHandler(),
133
137
  "llamaindex_single_agent_tool_handler": LlamaIndexSingleAgenttToolHandlerWrapper(),
134
- "lambda_func_handler": lambdaSpanHandler(),
138
+ "lambda_func_handler": lambdaSpanHandler()
135
139
  }
@@ -11,7 +11,7 @@ A2A_CLIENT_METHODS = [
11
11
  # "output_processor": A2A_RESOLVE,
12
12
  # },
13
13
  {
14
- "package": "a2a.client.client",
14
+ "package": "a2a.client",
15
15
  "object": "A2AClient",
16
16
  "method": "send_message",
17
17
  "wrapper_method": atask_wrapper,
@@ -4,6 +4,7 @@ This module provides utility functions to extract various attributes from agent
4
4
  """
5
5
 
6
6
  from ast import arguments
7
+ import json
7
8
  from typing import Any, Dict, Optional
8
9
  from monocle_apptrace.instrumentation.metamodel.finish_types import map_adk_finish_reason_to_finish_type
9
10
 
@@ -82,7 +83,7 @@ def extract_agent_input(arguments: Dict[str, Any]) -> Any:
82
83
  Returns:
83
84
  Any: The extracted input data
84
85
  """
85
- return arguments['args'][0].user_content.parts[0].text
86
+ return [arguments['args'][0].user_content.parts[0].text]
86
87
 
87
88
  def extract_agent_request_input(arguments: Dict[str, Any]) -> Any:
88
89
  """
@@ -94,7 +95,7 @@ def extract_agent_request_input(arguments: Dict[str, Any]) -> Any:
94
95
  Returns:
95
96
  Any: The extracted input data
96
97
  """
97
- return arguments['kwargs']['new_message'].parts[0].text if 'new_message' in arguments['kwargs'] else None
98
+ return [arguments['kwargs']['new_message'].parts[0].text] if 'new_message' in arguments['kwargs'] else []
98
99
 
99
100
  def extract_agent_response(result: Any) -> Any:
100
101
  """
@@ -107,7 +108,9 @@ def extract_agent_response(result: Any) -> Any:
107
108
  Any: The extracted response data
108
109
  """
109
110
  if result:
110
- return result.content.parts[0].text
111
+ return str(result.content.parts[0].text)
112
+ else:
113
+ return ""
111
114
 
112
115
  def get_tool_name(instance: Any) -> str:
113
116
  """
@@ -179,7 +182,7 @@ def extract_tool_input(arguments: Dict[str, Any]) -> Any:
179
182
  Returns:
180
183
  Any: The extracted input data
181
184
  """
182
- return str(arguments['kwargs'].get('args'))
185
+ return json.dumps(arguments['kwargs'].get('args', {}))
183
186
 
184
187
  def extract_tool_response(result: Any) -> Any:
185
188
  """
@@ -1,6 +1,7 @@
1
1
  from monocle_apptrace.instrumentation.common.constants import SPAN_SUBTYPES, SPAN_TYPES
2
2
  from monocle_apptrace.instrumentation.common.utils import get_error_message
3
3
  from monocle_apptrace.instrumentation.metamodel.adk import _helper
4
+ from monocle_apptrace.instrumentation.common.utils import get_error_message
4
5
  AGENT = {
5
6
  "type": SPAN_TYPES.AGENTIC_INVOCATION,
6
7
  "subtype": SPAN_SUBTYPES.ROUTING,
@@ -34,7 +35,7 @@ AGENT = {
34
35
  "attributes": [
35
36
  {
36
37
  "_comment": "this is Agent input",
37
- "attribute": "query",
38
+ "attribute": "input",
38
39
  "accessor": lambda arguments: _helper.extract_agent_input(arguments)
39
40
  }
40
41
  ]
@@ -42,6 +43,10 @@ AGENT = {
42
43
  {
43
44
  "name":"data.output",
44
45
  "attributes": [
46
+ {
47
+ "attribute": "error_code",
48
+ "accessor": lambda arguments: get_error_message(arguments)
49
+ },
45
50
  {
46
51
  "_comment": "this is response from LLM",
47
52
  "attribute": "response",
@@ -50,21 +50,21 @@ def extract_agent_input(arguments):
50
50
  if len(arguments["args"]) > 1:
51
51
  input_data = arguments["args"][1]
52
52
  if isinstance(input_data, str):
53
- return input_data
53
+ return [input_data]
54
54
  elif isinstance(input_data, list):
55
55
  # Handle list of input items
56
- return get_json_dumps(input_data)
56
+ return input_data
57
57
 
58
58
  # Fallback to kwargs
59
59
  if "original_input" in arguments["kwargs"]:
60
60
  input_data = arguments["kwargs"]["original_input"]
61
61
  if isinstance(input_data, str):
62
- return input_data
62
+ return [input_data]
63
63
  elif isinstance(input_data, list):
64
- return get_json_dumps(input_data)
64
+ return input_data
65
65
  except Exception as e:
66
66
  logger.warning("Warning: Error occurred in extract_agent_input: %s", str(e))
67
- return None
67
+ return []
68
68
 
69
69
 
70
70
  def get_agent_name(arguments) -> str:
@@ -134,12 +134,12 @@ def extract_tool_input(arguments):
134
134
  1
135
135
  ] # Second argument is usually the JSON string with params
136
136
  if isinstance(tool_input, str):
137
- return [tool_input]
137
+ return tool_input
138
138
  elif isinstance(tool_input, dict):
139
- return [get_json_dumps(tool_input)]
139
+ return get_json_dumps(tool_input)
140
140
 
141
141
  # Fallback to all args
142
- return [str(arg) for arg in arguments["args"]]
142
+ return str(arguments["args"])
143
143
  except Exception as e:
144
144
  logger.warning("Warning: Error occurred in extract_tool_input: %s", str(e))
145
145
  return []
@@ -1,6 +1,7 @@
1
1
  from monocle_apptrace.instrumentation.common.constants import AGENT_REQUEST_SPAN_NAME, SPAN_SUBTYPES, SPAN_TYPES
2
2
  from monocle_apptrace.instrumentation.common.utils import get_error_message
3
3
  from monocle_apptrace.instrumentation.metamodel.agents import _helper
4
+ from monocle_apptrace.instrumentation.common.utils import get_error_message
4
5
 
5
6
  AGENT = {
6
7
  "type": SPAN_TYPES.AGENTIC_INVOCATION,
@@ -35,7 +36,7 @@ AGENT = {
35
36
  "attributes": [
36
37
  {
37
38
  "_comment": "this is Agent input",
38
- "attribute": "query",
39
+ "attribute": "input",
39
40
  "accessor": lambda arguments: _helper.extract_agent_input(
40
41
  arguments
41
42
  ),
@@ -45,6 +46,10 @@ AGENT = {
45
46
  {
46
47
  "name": "data.output",
47
48
  "attributes": [
49
+ {
50
+ "attribute": "error_code",
51
+ "accessor": lambda arguments: get_error_message(arguments)
52
+ },
48
53
  {
49
54
  "_comment": "this is response from Agent",
50
55
  "attribute": "response",
@@ -73,7 +78,7 @@ AGENT = {
73
78
  }
74
79
 
75
80
  AGENT_REQUEST = {
76
- "type": AGENT_REQUEST_SPAN_NAME,
81
+ "type": SPAN_TYPES.AGENTIC_REQUEST,
77
82
  "subtype": SPAN_SUBTYPES.PLANNING,
78
83
  "attributes": [
79
84
  [
@@ -123,6 +128,7 @@ TOOLS = {
123
128
  {
124
129
  "_comment": "tool type",
125
130
  "attribute": "type",
131
+ "phase": "post_execution",
126
132
  "accessor": lambda arguments: _helper.get_tool_type(arguments["span"]),
127
133
  },
128
134
  {
@@ -201,6 +207,7 @@ AGENT_DELEGATION = {
201
207
  {
202
208
  "_comment": "name of the target agent",
203
209
  "attribute": "to_agent",
210
+ "phase": "post_execution",
204
211
  "accessor": lambda arguments: _helper.extract_handoff_target(arguments),
205
212
  },
206
213
  ]
@@ -67,7 +67,7 @@ def get_function_name(args) -> str:
67
67
  class aiohttpSpanHandler(SpanHandler):
68
68
 
69
69
  def pre_tracing(self, to_wrap, wrapped, instance, args, kwargs):
70
- return aiohttp_pre_tracing(args)
70
+ return aiohttp_pre_tracing(args), None
71
71
 
72
72
  def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value, token):
73
73
  aiohttp_post_tracing(token)
@@ -6,6 +6,7 @@ from monocle_apptrace.instrumentation.common.utils import (get_error_message, re
6
6
 
7
7
  INFERENCE = {
8
8
  "type": SPAN_TYPES.INFERENCE,
9
+ "subtype": lambda arguments: _helper.agent_inference_type(arguments),
9
10
  "attributes": [
10
11
  [
11
12
  {
@@ -80,10 +81,6 @@ INFERENCE = {
80
81
  "_comment": "finish type mapped from finish reason",
81
82
  "attribute": "finish_type",
82
83
  "accessor": lambda arguments: _helper.map_finish_reason_to_finish_type(_helper.extract_finish_reason(arguments))
83
- },
84
- {
85
- "attribute": "inference_sub_type",
86
- "accessor": lambda arguments: _helper.agent_inference_type(arguments)
87
84
  }
88
85
  ]
89
86
  }
@@ -84,7 +84,7 @@ def azure_func_post_tracing(token):
84
84
  class azureSpanHandler(SpanHandler):
85
85
 
86
86
  def pre_tracing(self, to_wrap, wrapped, instance, args, kwargs):
87
- return azure_func_pre_tracing(kwargs)
87
+ return azure_func_pre_tracing(kwargs), None
88
88
 
89
89
  def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value, token):
90
90
  azure_func_post_tracing(token)
@@ -7,6 +7,8 @@ import logging
7
7
  import json
8
8
  from io import BytesIO
9
9
  from functools import wraps
10
+
11
+ from rfc3986 import urlparse
10
12
  from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
11
13
  from monocle_apptrace.instrumentation.common.utils import ( get_exception_message, get_json_dumps, get_status_code,)
12
14
  from monocle_apptrace.instrumentation.metamodel.finish_types import map_bedrock_finish_reason_to_finish_type
@@ -194,3 +196,6 @@ def extract_finish_reason(arguments):
194
196
  def map_finish_reason_to_finish_type(finish_reason):
195
197
  """Map Bedrock finish_reason/stopReason to finish_type."""
196
198
  return map_bedrock_finish_reason_to_finish_type(finish_reason)
199
+
200
+ def extract_provider_name(instance):
201
+ return urlparse(instance.meta.endpoint_url).hostname
@@ -15,6 +15,10 @@ INFERENCE = {
15
15
  {
16
16
  "attribute": "inference_endpoint",
17
17
  "accessor": lambda arguments: arguments['instance'].meta.endpoint_url
18
+ },
19
+ {
20
+ "attribute": "provider_name",
21
+ "accessor": lambda arguments: _helper.extract_provider_name(arguments['instance'])
18
22
  }
19
23
  ],
20
24
  [
@@ -77,12 +77,12 @@ class FastAPISpanHandler(SpanHandler):
77
77
  fastapi_pre_tracing(scope)
78
78
  return super().pre_tracing(to_wrap, wrapped, instance, args, kwargs)
79
79
 
80
- def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
80
+ def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value, token):
81
81
  fastapi_post_tracing()
82
- return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
82
+ return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value, token)
83
83
 
84
84
  class FastAPIResponseSpanHandler(SpanHandler):
85
- def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
85
+ def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value, token):
86
86
  try:
87
87
  ctx = get_current()
88
88
  if ctx is not None:
@@ -92,4 +92,4 @@ class FastAPIResponseSpanHandler(SpanHandler):
92
92
  return_value, parent_span=parent_span)
93
93
  except Exception as e:
94
94
  logger.info(f"Failed to propagate fastapi response: {e}")
95
- super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
95
+ super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value, token)
@@ -3,10 +3,10 @@ from monocle_apptrace.instrumentation.metamodel.fastapi.entities.http import FAS
3
3
 
4
4
  FASTAPI_METHODS = [
5
5
  {
6
- "package": "fastapi",
7
- "object": "FastAPI",
8
- "method": "__call__",
9
- "wrapper_method": task_wrapper,
6
+ "package": "fastapi.routing",
7
+ "object": "APIRoute",
8
+ "method": "handle",
9
+ "wrapper_method": atask_wrapper,
10
10
  "span_name": "fastapi.request",
11
11
  "span_handler": "fastapi_handler",
12
12
  "output_processor": FASTAPI_HTTP_PROCESSOR,