monocle-apptrace 0.3.0b6__py3-none-any.whl → 0.3.1__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 (50) hide show
  1. monocle_apptrace/__init__.py +1 -0
  2. monocle_apptrace/exporters/aws/s3_exporter.py +20 -6
  3. monocle_apptrace/exporters/aws/s3_exporter_opendal.py +22 -11
  4. monocle_apptrace/exporters/azure/blob_exporter.py +22 -8
  5. monocle_apptrace/exporters/azure/blob_exporter_opendal.py +23 -8
  6. monocle_apptrace/exporters/exporter_processor.py +128 -3
  7. monocle_apptrace/exporters/file_exporter.py +16 -0
  8. monocle_apptrace/exporters/monocle_exporters.py +15 -3
  9. monocle_apptrace/exporters/okahu/okahu_exporter.py +8 -6
  10. monocle_apptrace/instrumentation/__init__.py +1 -0
  11. monocle_apptrace/instrumentation/common/__init__.py +2 -0
  12. monocle_apptrace/instrumentation/common/constants.py +7 -1
  13. monocle_apptrace/instrumentation/common/instrumentor.py +105 -20
  14. monocle_apptrace/instrumentation/common/span_handler.py +46 -28
  15. monocle_apptrace/instrumentation/common/tracing.md +68 -0
  16. monocle_apptrace/instrumentation/common/utils.py +70 -26
  17. monocle_apptrace/instrumentation/common/wrapper.py +27 -23
  18. monocle_apptrace/instrumentation/common/wrapper_method.py +5 -2
  19. monocle_apptrace/instrumentation/metamodel/anthropic/__init__.py +0 -0
  20. monocle_apptrace/instrumentation/metamodel/anthropic/_helper.py +64 -0
  21. monocle_apptrace/instrumentation/metamodel/anthropic/entities/__init__.py +0 -0
  22. monocle_apptrace/instrumentation/metamodel/anthropic/entities/inference.py +72 -0
  23. monocle_apptrace/instrumentation/metamodel/anthropic/methods.py +24 -0
  24. monocle_apptrace/instrumentation/metamodel/botocore/entities/inference.py +2 -2
  25. monocle_apptrace/instrumentation/metamodel/botocore/handlers/botocore_span_handler.py +2 -1
  26. monocle_apptrace/instrumentation/metamodel/flask/_helper.py +45 -3
  27. monocle_apptrace/instrumentation/metamodel/flask/entities/http.py +49 -0
  28. monocle_apptrace/instrumentation/metamodel/flask/methods.py +10 -1
  29. monocle_apptrace/instrumentation/metamodel/haystack/entities/inference.py +4 -1
  30. monocle_apptrace/instrumentation/metamodel/haystack/methods.py +1 -4
  31. monocle_apptrace/instrumentation/metamodel/langchain/_helper.py +12 -4
  32. monocle_apptrace/instrumentation/metamodel/langchain/methods.py +6 -14
  33. monocle_apptrace/instrumentation/metamodel/llamaindex/methods.py +2 -15
  34. monocle_apptrace/instrumentation/metamodel/openai/_helper.py +9 -4
  35. monocle_apptrace/instrumentation/metamodel/openai/methods.py +16 -2
  36. monocle_apptrace/instrumentation/metamodel/requests/_helper.py +31 -0
  37. monocle_apptrace/instrumentation/metamodel/requests/entities/http.py +51 -0
  38. monocle_apptrace/instrumentation/metamodel/requests/methods.py +2 -1
  39. monocle_apptrace/instrumentation/metamodel/teamsai/__init__.py +0 -0
  40. monocle_apptrace/instrumentation/metamodel/teamsai/_helper.py +58 -0
  41. monocle_apptrace/instrumentation/metamodel/teamsai/entities/__init__.py +0 -0
  42. monocle_apptrace/instrumentation/metamodel/teamsai/entities/inference/__init__.py +0 -0
  43. monocle_apptrace/instrumentation/metamodel/teamsai/entities/inference/actionplanner_output_processor.py +80 -0
  44. monocle_apptrace/instrumentation/metamodel/teamsai/entities/inference/teamsai_output_processor.py +70 -0
  45. monocle_apptrace/instrumentation/metamodel/teamsai/methods.py +26 -0
  46. {monocle_apptrace-0.3.0b6.dist-info → monocle_apptrace-0.3.1.dist-info}/METADATA +2 -1
  47. {monocle_apptrace-0.3.0b6.dist-info → monocle_apptrace-0.3.1.dist-info}/RECORD +50 -35
  48. {monocle_apptrace-0.3.0b6.dist-info → monocle_apptrace-0.3.1.dist-info}/WHEEL +0 -0
  49. {monocle_apptrace-0.3.0b6.dist-info → monocle_apptrace-0.3.1.dist-info}/licenses/LICENSE +0 -0
  50. {monocle_apptrace-0.3.0b6.dist-info → monocle_apptrace-0.3.1.dist-info}/licenses/NOTICE +0 -0
@@ -11,7 +11,7 @@ from monocle_apptrace.instrumentation.common.utils import (
11
11
  remove_scope,
12
12
  async_wrapper
13
13
  )
14
- from monocle_apptrace.instrumentation.common.constants import WORKFLOW_TYPE_KEY
14
+ from monocle_apptrace.instrumentation.common.constants import WORKFLOW_TYPE_KEY, ADD_NEW_WORKFLOW
15
15
  logger = logging.getLogger(__name__)
16
16
 
17
17
  def wrapper_processor(async_task: bool, tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
@@ -19,9 +19,7 @@ def wrapper_processor(async_task: bool, tracer: Tracer, handler: SpanHandler, to
19
19
  if instance.__class__.__name__ in ("AgentExecutor"):
20
20
  return wrapped(*args, **kwargs)
21
21
 
22
- if hasattr(instance, "name") and instance.name:
23
- name = f"{to_wrap.get('span_name')}.{instance.name.lower()}"
24
- elif to_wrap.get("span_name"):
22
+ if to_wrap.get("span_name"):
25
23
  name = to_wrap.get("span_name")
26
24
  else:
27
25
  name = get_fully_qualified_class_name(instance)
@@ -30,39 +28,44 @@ def wrapper_processor(async_task: bool, tracer: Tracer, handler: SpanHandler, to
30
28
  token = None
31
29
  try:
32
30
  handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
33
- skip_scan:bool = to_wrap.get('skip_span') or handler.skip_span(to_wrap, wrapped, instance, args, kwargs)
34
- token = SpanHandler.attach_workflow_type(to_wrap=to_wrap)
35
- if skip_scan:
31
+ if to_wrap.get('skip_span', False) or handler.skip_span(to_wrap, wrapped, instance, args, kwargs):
36
32
  if async_task:
37
- return_value = async_wrapper(wrapped, None, None, *args, **kwargs)
33
+ return_value = async_wrapper(wrapped, None, None, None, *args, **kwargs)
38
34
  else:
39
35
  return_value = wrapped(*args, **kwargs)
40
36
  else:
41
- return_value = span_processor(name, async_task, tracer, handler, to_wrap, wrapped, instance, args, kwargs)
37
+ add_workflow_span = get_value(ADD_NEW_WORKFLOW) == True
38
+ token = attach(set_value(ADD_NEW_WORKFLOW, False))
39
+ try:
40
+ return_value = span_processor(name, async_task, tracer, handler, add_workflow_span,
41
+ to_wrap, wrapped, instance, args, kwargs)
42
+ finally:
43
+ detach(token)
42
44
  return return_value
43
45
  finally:
44
- handler.detach_workflow_type(token)
45
46
  handler.post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
46
47
 
47
- def span_processor(name: str, async_task: bool, tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
48
+ def span_processor(name: str, async_task: bool, tracer: Tracer, handler: SpanHandler, add_workflow_span:bool,
49
+ to_wrap, wrapped, instance, args, kwargs):
48
50
  # For singleton spans, eg OpenAI inference generate a workflow span to format the workflow specific attributes
49
51
  return_value = None
50
52
  with tracer.start_as_current_span(name) as span:
51
53
  # Since Spanhandler can be overridden, ensure we set default monocle attributes.
52
54
  SpanHandler.set_default_monocle_attributes(span)
53
- if SpanHandler.is_root_span(span):
54
- SpanHandler.set_workflow_properties(span, to_wrap)
55
- if handler.is_non_workflow_root_span(span, to_wrap):
55
+ if SpanHandler.is_root_span(span) or add_workflow_span:
56
56
  # This is a direct API call of a non-framework type, call the span_processor recursively for the actual span
57
- return_value = span_processor(name, async_task, tracer, handler, to_wrap, wrapped, instance, args, kwargs)
57
+ SpanHandler.set_workflow_properties(span, to_wrap)
58
+ return_value = span_processor(name, async_task, tracer, handler, False, to_wrap, wrapped, instance, args, kwargs)
58
59
  else:
59
- handler.pre_task_processing(to_wrap, wrapped, instance, args, kwargs, span)
60
- if async_task:
61
- return_value = async_wrapper(wrapped, None, None, *args, **kwargs)
62
- else:
63
- return_value = wrapped(*args, **kwargs)
64
- handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, return_value, span)
65
- handler.post_task_processing(to_wrap, wrapped, instance, args, kwargs, return_value, span)
60
+ with SpanHandler.workflow_type(to_wrap):
61
+ SpanHandler.set_non_workflow_properties(span)
62
+ handler.pre_task_processing(to_wrap, wrapped, instance, args, kwargs, span)
63
+ if async_task:
64
+ return_value = async_wrapper(wrapped, None, None, None, *args, **kwargs)
65
+ else:
66
+ return_value = wrapped(*args, **kwargs)
67
+ handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, return_value, span)
68
+ handler.post_task_processing(to_wrap, wrapped, instance, args, kwargs, return_value, span)
66
69
  return return_value
67
70
 
68
71
  @with_tracer_wrapper
@@ -86,5 +89,6 @@ def scope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instan
86
89
  @with_tracer_wrapper
87
90
  async def ascope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
88
91
  scope_name = to_wrap.get('scope_name', None)
89
- return_value = async_wrapper(wrapped, scope_name, None, *args, **kwargs)
92
+ scope_value = to_wrap.get('scope_value', None)
93
+ return_value = async_wrapper(wrapped, scope_name, scope_value, None, *args, **kwargs)
90
94
  return return_value
@@ -12,9 +12,11 @@ from monocle_apptrace.instrumentation.metamodel.haystack.methods import (HAYSTAC
12
12
  from monocle_apptrace.instrumentation.metamodel.openai.methods import (OPENAI_METHODS,)
13
13
  from monocle_apptrace.instrumentation.metamodel.langgraph.methods import LANGGRAPH_METHODS
14
14
  from monocle_apptrace.instrumentation.metamodel.flask.methods import (FLASK_METHODS, )
15
- from monocle_apptrace.instrumentation.metamodel.flask._helper import FlaskSpanHandler
15
+ from monocle_apptrace.instrumentation.metamodel.flask._helper import FlaskSpanHandler, FlaskResponseSpanHandler
16
16
  from monocle_apptrace.instrumentation.metamodel.requests.methods import (REQUESTS_METHODS, )
17
17
  from monocle_apptrace.instrumentation.metamodel.requests._helper import RequestSpanHandler
18
+ from monocle_apptrace.instrumentation.metamodel.teamsai.methods import (TEAMAI_METHODS, )
19
+ from monocle_apptrace.instrumentation.metamodel.anthropic.methods import (ANTHROPIC_METHODS, )
18
20
 
19
21
  class WrapperMethod:
20
22
  def __init__(
@@ -61,12 +63,13 @@ class WrapperMethod:
61
63
  def get_span_handler(self) -> SpanHandler:
62
64
  return self.span_handler()
63
65
 
64
- DEFAULT_METHODS_LIST = LANGCHAIN_METHODS + LLAMAINDEX_METHODS + HAYSTACK_METHODS + BOTOCORE_METHODS + FLASK_METHODS + REQUESTS_METHODS + LANGGRAPH_METHODS + OPENAI_METHODS
66
+ DEFAULT_METHODS_LIST = LANGCHAIN_METHODS + LLAMAINDEX_METHODS + HAYSTACK_METHODS + BOTOCORE_METHODS + FLASK_METHODS + REQUESTS_METHODS + LANGGRAPH_METHODS + OPENAI_METHODS + TEAMAI_METHODS + ANTHROPIC_METHODS
65
67
 
66
68
  MONOCLE_SPAN_HANDLERS: Dict[str, SpanHandler] = {
67
69
  "default": SpanHandler(),
68
70
  "botocore_handler": BotoCoreSpanHandler(),
69
71
  "flask_handler": FlaskSpanHandler(),
72
+ "flask_response_handler": FlaskResponseSpanHandler(),
70
73
  "request_handler": RequestSpanHandler(),
71
74
  "non_framework_handler": NonFrameworkSpanHandler()
72
75
  }
@@ -0,0 +1,64 @@
1
+ """
2
+ This module provides utility functions for extracting system, user,
3
+ and assistant messages from various input formats.
4
+ """
5
+
6
+ import logging
7
+ from monocle_apptrace.instrumentation.common.utils import (
8
+ Option,
9
+ get_keys_as_tuple,
10
+ get_nested_value,
11
+ try_option,
12
+ )
13
+
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ def extract_provider_name(instance):
18
+ provider_url: Option[str] = try_option(getattr, instance._client.base_url, 'host')
19
+ return provider_url.unwrap_or(None)
20
+
21
+ def extract_inference_endpoint(instance):
22
+ inference_endpoint: Option[str] = try_option(getattr, instance._client, 'base_url').map(str)
23
+ if inference_endpoint.is_none() and "meta" in instance.client.__dict__:
24
+ inference_endpoint = try_option(getattr, instance.client.meta, 'endpoint_url').map(str)
25
+
26
+ return inference_endpoint.unwrap_or(extract_provider_name(instance))
27
+
28
+ def extract_messages(kwargs):
29
+ """Extract system and user messages"""
30
+ try:
31
+ messages = []
32
+ if 'messages' in kwargs and len(kwargs['messages']) >0:
33
+ for msg in kwargs['messages']:
34
+ if msg.get('content') and msg.get('role'):
35
+ messages.append({msg['role']: msg['content']})
36
+
37
+ return [str(message) for message in messages]
38
+ except Exception as e:
39
+ logger.warning("Warning: Error occurred in extract_messages: %s", str(e))
40
+ return []
41
+
42
+
43
+ def extract_assistant_message(response):
44
+ try:
45
+ if response is not None and hasattr(response,"content") and len(response.content) >0:
46
+ if hasattr(response.content[0],"text"):
47
+ return response.content[0].text
48
+ except (IndexError, AttributeError) as e:
49
+ logger.warning("Warning: Error occurred in extract_assistant_message: %s", str(e))
50
+ return None
51
+
52
+ def update_span_from_llm_response(response):
53
+ meta_dict = {}
54
+ if response is not None and hasattr(response, "usage"):
55
+ if hasattr(response, "usage") and response.usage is not None:
56
+ token_usage = response.usage
57
+ else:
58
+ response_metadata = response.response_metadata
59
+ token_usage = response_metadata.get("token_usage")
60
+ if token_usage is not None:
61
+ meta_dict.update({"completion_tokens": getattr(response.usage, "output_tokens", 0)})
62
+ meta_dict.update({"prompt_tokens": getattr(response.usage, "input_tokens", 0)})
63
+ meta_dict.update({"total_tokens": getattr(response.usage, "input_tokens", 0)+getattr(response.usage, "output_tokens", 0)})
64
+ return meta_dict
@@ -0,0 +1,72 @@
1
+ from monocle_apptrace.instrumentation.metamodel.anthropic import (
2
+ _helper,
3
+ )
4
+ from monocle_apptrace.instrumentation.common.utils import resolve_from_alias, get_llm_type
5
+
6
+ INFERENCE = {
7
+ "type": "inference",
8
+ "attributes": [
9
+ [
10
+ {
11
+ "_comment": "provider type ,name , deployment , inference_endpoint",
12
+ "attribute": "type",
13
+ "accessor": lambda arguments: 'inference.' + (get_llm_type(arguments['instance']) or 'generic')
14
+
15
+ },
16
+ {
17
+ "attribute": "provider_name",
18
+ "accessor": lambda arguments: _helper.extract_provider_name(arguments['instance'])
19
+ },
20
+ {
21
+ "attribute": "deployment",
22
+ "accessor": lambda arguments: resolve_from_alias(arguments['instance'].__dict__, ['engine', 'azure_deployment', 'deployment_name', 'deployment_id', 'deployment'])
23
+ },
24
+ {
25
+ "attribute": "inference_endpoint",
26
+ "accessor": lambda arguments: resolve_from_alias(arguments['instance'].__dict__, ['azure_endpoint', 'api_base', 'endpoint']) or _helper.extract_inference_endpoint(arguments['instance'])
27
+ }
28
+ ],
29
+ [
30
+ {
31
+ "_comment": "LLM Model",
32
+ "attribute": "name",
33
+ "accessor": lambda arguments: resolve_from_alias(arguments['kwargs'], ['model', 'model_name', 'endpoint_name', 'deployment_name'])
34
+ },
35
+ {
36
+ "attribute": "type",
37
+ "accessor": lambda arguments: 'model.llm.' + resolve_from_alias(arguments['kwargs'], ['model', 'model_name', 'endpoint_name', 'deployment_name'])
38
+ }
39
+ ]
40
+ ],
41
+ "events": [
42
+ {"name": "data.input",
43
+ "attributes": [
44
+
45
+ {
46
+ "_comment": "this is instruction and user query to LLM",
47
+ "attribute": "input",
48
+ "accessor": lambda arguments: _helper.extract_messages(arguments['kwargs'])
49
+ }
50
+ ]
51
+ },
52
+ {
53
+ "name": "data.output",
54
+ "attributes": [
55
+ {
56
+ "_comment": "this is result from LLM",
57
+ "attribute": "response",
58
+ "accessor": lambda arguments: _helper.extract_assistant_message(arguments['result'])
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ "name": "metadata",
64
+ "attributes": [
65
+ {
66
+ "_comment": "this is metadata usage from LLM",
67
+ "accessor": lambda arguments: _helper.update_span_from_llm_response(arguments['result'])
68
+ }
69
+ ]
70
+ }
71
+ ]
72
+ }
@@ -0,0 +1,24 @@
1
+ from monocle_apptrace.instrumentation.common.wrapper import atask_wrapper, task_wrapper
2
+ from monocle_apptrace.instrumentation.metamodel.anthropic.entities.inference import (
3
+ INFERENCE,
4
+ )
5
+
6
+ ANTHROPIC_METHODS = [
7
+ {
8
+ "package": "anthropic.resources",
9
+ "object": "Messages",
10
+ "method": "create",
11
+ "wrapper_method": task_wrapper,
12
+ "span_handler": "non_framework_handler",
13
+ "output_processor": INFERENCE
14
+ },
15
+ {
16
+ "package": "anthropic.resources",
17
+ "object": "AsyncMessages",
18
+ "method": "create",
19
+ "wrapper_method": atask_wrapper,
20
+ "span_handler": "non_framework_handler",
21
+ "output_processor": INFERENCE
22
+ },
23
+
24
+ ]
@@ -1,7 +1,7 @@
1
1
  from monocle_apptrace.instrumentation.metamodel.botocore import (
2
2
  _helper,
3
3
  )
4
-
4
+ from monocle_apptrace.instrumentation.common.utils import get_llm_type
5
5
  INFERENCE = {
6
6
  "type": "inference",
7
7
  "attributes": [
@@ -9,7 +9,7 @@ INFERENCE = {
9
9
  {
10
10
  "_comment": "provider type , inference_endpoint",
11
11
  "attribute": "type",
12
- "accessor": lambda arguments: 'inference.aws_sagemaker'
12
+ "accessor": lambda arguments: 'inference.'+(get_llm_type(arguments['instance']) or 'generic')
13
13
  },
14
14
  {
15
15
  "attribute": "inference_endpoint",
@@ -1,3 +1,4 @@
1
+ from opentelemetry.context import get_value, set_value, attach, detach
1
2
  from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
2
3
 
3
4
  class BotoCoreSpanHandler(SpanHandler):
@@ -22,4 +23,4 @@ class BotoCoreSpanHandler(SpanHandler):
22
23
  def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
23
24
  self._botocore_processor(to_wrap=to_wrap, wrapped=wrapped, instance=instance, return_value=return_value, args=args,
24
25
  kwargs=kwargs)
25
- return super().pre_tracing(to_wrap, wrapped, instance, args, kwargs)
26
+ return super().post_tracing(to_wrap, wrapped, instance, args, kwargs,return_value)
@@ -1,11 +1,41 @@
1
+ import logging
1
2
  from threading import local
2
3
  from monocle_apptrace.instrumentation.common.utils import extract_http_headers, clear_http_scopes
3
- from opentelemetry.propagate import extract
4
- from opentelemetry.context import Context, attach, detach
5
4
  from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
5
+ from urllib.parse import unquote
6
+ from opentelemetry.context import get_current
7
+ from opentelemetry.trace import Span, get_current_span
8
+ from opentelemetry.trace.propagation import _SPAN_KEY
9
+
10
+ logger = logging.getLogger(__name__)
11
+ MAX_DATA_LENGTH = 1000
6
12
  token_data = local()
7
13
  token_data.current_token = None
8
14
 
15
+ def get_route(args) -> str:
16
+ return args[0]['PATH_INFO'] if 'PATH_INFO' in args[0] else ""
17
+
18
+ def get_method(args) -> str:
19
+ return args[0]['REQUEST_METHOD'] if 'REQUEST_METHOD' in args[0] else ""
20
+
21
+ def get_params(args) -> dict:
22
+ params = args[0]['QUERY_STRING'] if 'QUERY_STRING' in args[0] else ""
23
+ return unquote(params)
24
+
25
+ def get_body(args) -> dict:
26
+ return ""
27
+
28
+ def extract_response(instance) -> str:
29
+ if hasattr(instance, 'data') and hasattr(instance, 'content_length'):
30
+ response = instance.data[0:max(instance.content_length, MAX_DATA_LENGTH)]
31
+ else:
32
+ response = ""
33
+ return response
34
+
35
+ def extract_status(instance) -> str:
36
+ status = instance.status if hasattr(instance, 'status') else ""
37
+ return status
38
+
9
39
  def flask_pre_tracing(args):
10
40
  headers = dict()
11
41
  for key, value in args[0].items():
@@ -26,4 +56,16 @@ class FlaskSpanHandler(SpanHandler):
26
56
 
27
57
  def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
28
58
  flask_post_tracing()
29
- return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
59
+ return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
60
+
61
+ class FlaskResponseSpanHandler(SpanHandler):
62
+ def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
63
+ try:
64
+ _parent_span_context = get_current()
65
+ if _parent_span_context is not None:
66
+ parent_span: Span = _parent_span_context.get(_SPAN_KEY, None)
67
+ if parent_span is not None:
68
+ self.hydrate_events(to_wrap, wrapped, instance, args, kwargs, return_value, parent_span)
69
+ except Exception as e:
70
+ logger.info(f"Failed to propogate flask response: {e}")
71
+ super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
@@ -0,0 +1,49 @@
1
+ from monocle_apptrace.instrumentation.metamodel.flask import _helper
2
+ FLASK_HTTP_PROCESSOR = {
3
+ "type": "http.process",
4
+ "attributes": [
5
+ [
6
+ {
7
+ "_comment": "request method, request URI",
8
+ "attribute": "method",
9
+ "accessor": lambda arguments: _helper.get_method(arguments['args'])
10
+ },
11
+ {
12
+ "_comment": "request method, request URI",
13
+ "attribute": "route",
14
+ "accessor": lambda arguments: _helper.get_route(arguments['args'])
15
+ },
16
+ ]
17
+ ]
18
+ }
19
+
20
+ FLASK_RESPONSE_PROCESSOR = {
21
+ "type": "http.process",
22
+ "events": [
23
+ {
24
+ "name": "data.input",
25
+ "attributes": [
26
+ {
27
+ "_comment": "route params",
28
+ "attribute": "params",
29
+ "accessor": lambda arguments: _helper.get_params(arguments['args'])
30
+ }
31
+ ]
32
+ },
33
+ {
34
+ "name": "data.output",
35
+ "attributes": [
36
+ {
37
+ "_comment": "status from HTTP response",
38
+ "attribute": "status",
39
+ "accessor": lambda arguments: _helper.extract_status(arguments['instance'])
40
+ },
41
+ {
42
+ "_comment": "this is result from LLM",
43
+ "attribute": "response",
44
+ "accessor": lambda arguments: _helper.extract_response(arguments['instance'])
45
+ }
46
+ ]
47
+ }
48
+ ]
49
+ }
@@ -1,13 +1,22 @@
1
1
  from monocle_apptrace.instrumentation.common.wrapper import task_wrapper
2
+ from monocle_apptrace.instrumentation.metamodel.flask.entities.http import FLASK_HTTP_PROCESSOR, FLASK_RESPONSE_PROCESSOR
2
3
 
3
4
  FLASK_METHODS = [
4
5
  {
5
6
  "package": "flask.app",
6
7
  "object": "Flask",
7
8
  "method": "wsgi_app",
8
- "span_name": "Flask.wsgi_app",
9
9
  "wrapper_method": task_wrapper,
10
10
  "span_handler": "flask_handler",
11
+ "output_processor": FLASK_HTTP_PROCESSOR,
12
+ },
13
+ {
14
+ "package": "werkzeug.wrappers.response",
15
+ "object": "Response",
16
+ "method": "__call__",
17
+ "wrapper_method": task_wrapper,
18
+ "span_handler": "flask_response_handler",
19
+ "output_processor": FLASK_RESPONSE_PROCESSOR,
11
20
  "skip_span": True
12
21
  }
13
22
  ]
@@ -1,6 +1,7 @@
1
1
  from monocle_apptrace.instrumentation.metamodel.haystack import (
2
2
  _helper,
3
3
  )
4
+ from monocle_apptrace.instrumentation.common.utils import get_llm_type
4
5
 
5
6
  INFERENCE = {
6
7
  "type": "inference",
@@ -9,7 +10,9 @@ INFERENCE = {
9
10
  {
10
11
  "_comment": "provider type ,name , deployment , inference_endpoint",
11
12
  "attribute": "type",
12
- "accessor": lambda arguments: 'inference.azure_openai'
13
+ # "accessor": lambda arguments: 'inference.azure_openai'
14
+ "accessor": lambda arguments: 'inference.' + (get_llm_type(arguments['instance']) or 'generic')
15
+
13
16
  },
14
17
  {
15
18
  "attribute": "provider_name",
@@ -7,7 +7,6 @@ HAYSTACK_METHODS = [
7
7
  "package": "haystack.components.retrievers.in_memory",
8
8
  "object": "InMemoryEmbeddingRetriever",
9
9
  "method": "run",
10
- "span_name": "haystack.retriever",
11
10
  "wrapper_method": task_wrapper,
12
11
  "output_processor": RETRIEVAL
13
12
  },
@@ -15,7 +14,6 @@ HAYSTACK_METHODS = [
15
14
  "package": "haystack_integrations.components.retrievers.opensearch",
16
15
  "object": "OpenSearchEmbeddingRetriever",
17
16
  "method": "run",
18
- "span_name": "haystack.retriever",
19
17
  "wrapper_method": task_wrapper,
20
18
  "output_processor": RETRIEVAL
21
19
  },
@@ -37,7 +35,6 @@ HAYSTACK_METHODS = [
37
35
  "package": "haystack.core.pipeline.pipeline",
38
36
  "object": "Pipeline",
39
37
  "method": "run",
40
- "wrapper_method": task_wrapper,
41
- "span_type": "workflow"
38
+ "wrapper_method": task_wrapper
42
39
  }
43
40
  ]
@@ -50,14 +50,22 @@ def extract_assistant_message(response):
50
50
 
51
51
 
52
52
  def extract_provider_name(instance):
53
- provider_url: Option[str] = try_option(getattr, instance.client._client.base_url, 'host')
53
+ provider_url: Option[str] = None
54
+ if hasattr(instance,'client'):
55
+ provider_url: Option[str] = try_option(getattr, instance.client._client.base_url, 'host')
56
+ if hasattr(instance, '_client'):
57
+ provider_url = try_option(getattr, instance._client.base_url, 'host')
54
58
  return provider_url.unwrap_or(None)
55
59
 
56
60
 
57
61
  def extract_inference_endpoint(instance):
58
- inference_endpoint: Option[str] = try_option(getattr, instance.client._client, 'base_url').map(str)
59
- if inference_endpoint.is_none() and "meta" in instance.client.__dict__:
60
- inference_endpoint = try_option(getattr, instance.client.meta, 'endpoint_url').map(str)
62
+ inference_endpoint: Option[str] = None
63
+ if hasattr(instance,'client'):
64
+ inference_endpoint: Option[str] = try_option(getattr, instance.client._client, 'base_url').map(str)
65
+ if inference_endpoint.is_none() and "meta" in instance.client.__dict__:
66
+ inference_endpoint = try_option(getattr, instance.client.meta, 'endpoint_url').map(str)
67
+ if hasattr(instance,'_client'):
68
+ inference_endpoint = try_option(getattr, instance._client, 'base_url').map(str)
61
69
 
62
70
  return inference_endpoint.unwrap_or(extract_provider_name(instance))
63
71
 
@@ -11,15 +11,13 @@ LANGCHAIN_METHODS = [
11
11
  "package": "langchain.prompts.base",
12
12
  "object": "BasePromptTemplate",
13
13
  "method": "invoke",
14
- "wrapper_method": task_wrapper,
15
- "span_type": "workflow"
14
+ "wrapper_method": task_wrapper
16
15
  },
17
16
  {
18
17
  "package": "langchain.prompts.base",
19
18
  "object": "BasePromptTemplate",
20
19
  "method": "ainvoke",
21
- "wrapper_method": atask_wrapper,
22
- "span_type": "workflow"
20
+ "wrapper_method": atask_wrapper
23
21
  },
24
22
  {
25
23
  "package": "langchain.chat_models.base",
@@ -82,30 +80,24 @@ LANGCHAIN_METHODS = [
82
80
  "package": "langchain.schema",
83
81
  "object": "BaseOutputParser",
84
82
  "method": "invoke",
85
- "wrapper_method": task_wrapper,
86
- "span_type": "workflow"
83
+ "wrapper_method": task_wrapper
87
84
  },
88
85
  {
89
86
  "package": "langchain.schema",
90
87
  "object": "BaseOutputParser",
91
88
  "method": "ainvoke",
92
- "wrapper_method": atask_wrapper,
93
- "span_type": "workflow"
89
+ "wrapper_method": atask_wrapper
94
90
  },
95
91
  {
96
92
  "package": "langchain.schema.runnable",
97
93
  "object": "RunnableSequence",
98
94
  "method": "invoke",
99
- "span_name": "langchain.workflow",
100
- "wrapper_method": task_wrapper,
101
- "span_type": "workflow"
95
+ "wrapper_method": task_wrapper
102
96
  },
103
97
  {
104
98
  "package": "langchain.schema.runnable",
105
99
  "object": "RunnableSequence",
106
100
  "method": "ainvoke",
107
- "span_name": "langchain.workflow",
108
- "wrapper_method": atask_wrapper,
109
- "span_type": "workflow"
101
+ "wrapper_method": atask_wrapper
110
102
  }
111
103
  ]