openlit 1.34.30__py3-none-any.whl → 1.34.31__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.
Files changed (168) hide show
  1. openlit/__helpers.py +235 -86
  2. openlit/__init__.py +16 -13
  3. openlit/_instrumentors.py +2 -1
  4. openlit/evals/all.py +50 -21
  5. openlit/evals/bias_detection.py +47 -20
  6. openlit/evals/hallucination.py +53 -22
  7. openlit/evals/toxicity.py +50 -21
  8. openlit/evals/utils.py +54 -30
  9. openlit/guard/all.py +61 -19
  10. openlit/guard/prompt_injection.py +34 -14
  11. openlit/guard/restrict_topic.py +46 -15
  12. openlit/guard/sensitive_topic.py +34 -14
  13. openlit/guard/utils.py +58 -22
  14. openlit/instrumentation/ag2/__init__.py +24 -8
  15. openlit/instrumentation/ag2/ag2.py +34 -13
  16. openlit/instrumentation/ag2/async_ag2.py +34 -13
  17. openlit/instrumentation/ag2/utils.py +133 -30
  18. openlit/instrumentation/ai21/__init__.py +43 -14
  19. openlit/instrumentation/ai21/ai21.py +47 -21
  20. openlit/instrumentation/ai21/async_ai21.py +47 -21
  21. openlit/instrumentation/ai21/utils.py +299 -78
  22. openlit/instrumentation/anthropic/__init__.py +21 -4
  23. openlit/instrumentation/anthropic/anthropic.py +28 -17
  24. openlit/instrumentation/anthropic/async_anthropic.py +28 -17
  25. openlit/instrumentation/anthropic/utils.py +145 -35
  26. openlit/instrumentation/assemblyai/__init__.py +11 -2
  27. openlit/instrumentation/assemblyai/assemblyai.py +15 -4
  28. openlit/instrumentation/assemblyai/utils.py +120 -25
  29. openlit/instrumentation/astra/__init__.py +43 -10
  30. openlit/instrumentation/astra/astra.py +28 -5
  31. openlit/instrumentation/astra/async_astra.py +28 -5
  32. openlit/instrumentation/astra/utils.py +151 -55
  33. openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
  34. openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
  35. openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
  36. openlit/instrumentation/azure_ai_inference/utils.py +307 -83
  37. openlit/instrumentation/bedrock/__init__.py +21 -4
  38. openlit/instrumentation/bedrock/bedrock.py +63 -25
  39. openlit/instrumentation/bedrock/utils.py +139 -30
  40. openlit/instrumentation/chroma/__init__.py +89 -16
  41. openlit/instrumentation/chroma/chroma.py +28 -6
  42. openlit/instrumentation/chroma/utils.py +167 -51
  43. openlit/instrumentation/cohere/__init__.py +63 -18
  44. openlit/instrumentation/cohere/async_cohere.py +63 -24
  45. openlit/instrumentation/cohere/cohere.py +63 -24
  46. openlit/instrumentation/cohere/utils.py +286 -73
  47. openlit/instrumentation/controlflow/__init__.py +35 -9
  48. openlit/instrumentation/controlflow/controlflow.py +66 -33
  49. openlit/instrumentation/crawl4ai/__init__.py +25 -10
  50. openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
  51. openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
  52. openlit/instrumentation/crewai/__init__.py +40 -15
  53. openlit/instrumentation/crewai/async_crewai.py +32 -7
  54. openlit/instrumentation/crewai/crewai.py +32 -7
  55. openlit/instrumentation/crewai/utils.py +159 -56
  56. openlit/instrumentation/dynamiq/__init__.py +46 -12
  57. openlit/instrumentation/dynamiq/dynamiq.py +74 -33
  58. openlit/instrumentation/elevenlabs/__init__.py +23 -4
  59. openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
  60. openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
  61. openlit/instrumentation/elevenlabs/utils.py +128 -25
  62. openlit/instrumentation/embedchain/__init__.py +11 -2
  63. openlit/instrumentation/embedchain/embedchain.py +68 -35
  64. openlit/instrumentation/firecrawl/__init__.py +24 -7
  65. openlit/instrumentation/firecrawl/firecrawl.py +46 -20
  66. openlit/instrumentation/google_ai_studio/__init__.py +45 -10
  67. openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
  68. openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
  69. openlit/instrumentation/google_ai_studio/utils.py +180 -67
  70. openlit/instrumentation/gpt4all/__init__.py +22 -7
  71. openlit/instrumentation/gpt4all/gpt4all.py +67 -29
  72. openlit/instrumentation/gpt4all/utils.py +285 -61
  73. openlit/instrumentation/gpu/__init__.py +128 -47
  74. openlit/instrumentation/groq/__init__.py +21 -4
  75. openlit/instrumentation/groq/async_groq.py +33 -21
  76. openlit/instrumentation/groq/groq.py +33 -21
  77. openlit/instrumentation/groq/utils.py +192 -55
  78. openlit/instrumentation/haystack/__init__.py +70 -24
  79. openlit/instrumentation/haystack/async_haystack.py +28 -6
  80. openlit/instrumentation/haystack/haystack.py +28 -6
  81. openlit/instrumentation/haystack/utils.py +196 -74
  82. openlit/instrumentation/julep/__init__.py +69 -19
  83. openlit/instrumentation/julep/async_julep.py +53 -27
  84. openlit/instrumentation/julep/julep.py +53 -28
  85. openlit/instrumentation/langchain/__init__.py +74 -63
  86. openlit/instrumentation/langchain/callback_handler.py +1100 -0
  87. openlit/instrumentation/langchain_community/__init__.py +13 -2
  88. openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
  89. openlit/instrumentation/langchain_community/langchain_community.py +23 -5
  90. openlit/instrumentation/langchain_community/utils.py +35 -9
  91. openlit/instrumentation/letta/__init__.py +68 -15
  92. openlit/instrumentation/letta/letta.py +99 -54
  93. openlit/instrumentation/litellm/__init__.py +43 -14
  94. openlit/instrumentation/litellm/async_litellm.py +51 -26
  95. openlit/instrumentation/litellm/litellm.py +51 -26
  96. openlit/instrumentation/litellm/utils.py +304 -102
  97. openlit/instrumentation/llamaindex/__init__.py +267 -90
  98. openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
  99. openlit/instrumentation/llamaindex/llamaindex.py +28 -6
  100. openlit/instrumentation/llamaindex/utils.py +204 -91
  101. openlit/instrumentation/mem0/__init__.py +11 -2
  102. openlit/instrumentation/mem0/mem0.py +50 -29
  103. openlit/instrumentation/milvus/__init__.py +10 -2
  104. openlit/instrumentation/milvus/milvus.py +31 -6
  105. openlit/instrumentation/milvus/utils.py +166 -67
  106. openlit/instrumentation/mistral/__init__.py +63 -18
  107. openlit/instrumentation/mistral/async_mistral.py +63 -24
  108. openlit/instrumentation/mistral/mistral.py +63 -24
  109. openlit/instrumentation/mistral/utils.py +277 -69
  110. openlit/instrumentation/multion/__init__.py +69 -19
  111. openlit/instrumentation/multion/async_multion.py +57 -26
  112. openlit/instrumentation/multion/multion.py +57 -26
  113. openlit/instrumentation/ollama/__init__.py +39 -18
  114. openlit/instrumentation/ollama/async_ollama.py +57 -26
  115. openlit/instrumentation/ollama/ollama.py +57 -26
  116. openlit/instrumentation/ollama/utils.py +226 -50
  117. openlit/instrumentation/openai/__init__.py +156 -32
  118. openlit/instrumentation/openai/async_openai.py +147 -67
  119. openlit/instrumentation/openai/openai.py +150 -67
  120. openlit/instrumentation/openai/utils.py +657 -185
  121. openlit/instrumentation/openai_agents/__init__.py +5 -1
  122. openlit/instrumentation/openai_agents/processor.py +110 -90
  123. openlit/instrumentation/phidata/__init__.py +13 -5
  124. openlit/instrumentation/phidata/phidata.py +67 -32
  125. openlit/instrumentation/pinecone/__init__.py +48 -9
  126. openlit/instrumentation/pinecone/async_pinecone.py +27 -5
  127. openlit/instrumentation/pinecone/pinecone.py +27 -5
  128. openlit/instrumentation/pinecone/utils.py +153 -47
  129. openlit/instrumentation/premai/__init__.py +22 -7
  130. openlit/instrumentation/premai/premai.py +51 -26
  131. openlit/instrumentation/premai/utils.py +246 -59
  132. openlit/instrumentation/pydantic_ai/__init__.py +49 -22
  133. openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
  134. openlit/instrumentation/pydantic_ai/utils.py +89 -24
  135. openlit/instrumentation/qdrant/__init__.py +19 -4
  136. openlit/instrumentation/qdrant/async_qdrant.py +33 -7
  137. openlit/instrumentation/qdrant/qdrant.py +33 -7
  138. openlit/instrumentation/qdrant/utils.py +228 -93
  139. openlit/instrumentation/reka/__init__.py +23 -10
  140. openlit/instrumentation/reka/async_reka.py +17 -11
  141. openlit/instrumentation/reka/reka.py +17 -11
  142. openlit/instrumentation/reka/utils.py +138 -36
  143. openlit/instrumentation/together/__init__.py +44 -12
  144. openlit/instrumentation/together/async_together.py +50 -27
  145. openlit/instrumentation/together/together.py +50 -27
  146. openlit/instrumentation/together/utils.py +301 -71
  147. openlit/instrumentation/transformers/__init__.py +2 -1
  148. openlit/instrumentation/transformers/transformers.py +13 -3
  149. openlit/instrumentation/transformers/utils.py +139 -36
  150. openlit/instrumentation/vertexai/__init__.py +81 -16
  151. openlit/instrumentation/vertexai/async_vertexai.py +33 -15
  152. openlit/instrumentation/vertexai/utils.py +123 -27
  153. openlit/instrumentation/vertexai/vertexai.py +33 -15
  154. openlit/instrumentation/vllm/__init__.py +12 -5
  155. openlit/instrumentation/vllm/utils.py +121 -31
  156. openlit/instrumentation/vllm/vllm.py +16 -10
  157. openlit/otel/events.py +35 -10
  158. openlit/otel/metrics.py +32 -24
  159. openlit/otel/tracing.py +24 -9
  160. openlit/semcov/__init__.py +72 -6
  161. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/METADATA +2 -1
  162. openlit-1.34.31.dist-info/RECORD +166 -0
  163. openlit/instrumentation/langchain/async_langchain.py +0 -102
  164. openlit/instrumentation/langchain/langchain.py +0 -102
  165. openlit/instrumentation/langchain/utils.py +0 -252
  166. openlit-1.34.30.dist-info/RECORD +0 -168
  167. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
  168. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/WHEEL +0 -0
@@ -6,12 +6,11 @@ import importlib.metadata
6
6
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
7
  from wrapt import wrap_function_wrapper
8
8
 
9
- from openlit.instrumentation.controlflow.controlflow import (
10
- wrap_controlflow
11
- )
9
+ from openlit.instrumentation.controlflow.controlflow import wrap_controlflow
12
10
 
13
11
  _instruments = ("controlflow >= 0.3.2",)
14
12
 
13
+
15
14
  class ControlFlowInstrumentor(BaseInstrumentor):
16
15
  """
17
16
  An instrumentor for controlflow's client library.
@@ -33,22 +32,49 @@ class ControlFlowInstrumentor(BaseInstrumentor):
33
32
  wrap_function_wrapper(
34
33
  "controlflow.agents.agent",
35
34
  "Agent.__init__",
36
- wrap_controlflow("controlflow.create_agent", version, environment, application_name,
37
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
35
+ wrap_controlflow(
36
+ "controlflow.create_agent",
37
+ version,
38
+ environment,
39
+ application_name,
40
+ tracer,
41
+ pricing_info,
42
+ capture_message_content,
43
+ metrics,
44
+ disable_metrics,
45
+ ),
38
46
  )
39
47
 
40
48
  wrap_function_wrapper(
41
49
  "controlflow.tasks.task",
42
50
  "Task.__init__",
43
- wrap_controlflow("controlflow.create_task", version, environment, application_name,
44
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
51
+ wrap_controlflow(
52
+ "controlflow.create_task",
53
+ version,
54
+ environment,
55
+ application_name,
56
+ tracer,
57
+ pricing_info,
58
+ capture_message_content,
59
+ metrics,
60
+ disable_metrics,
61
+ ),
45
62
  )
46
63
 
47
64
  wrap_function_wrapper(
48
65
  "controlflow",
49
66
  "run",
50
- wrap_controlflow("controlflow.run", version, environment, application_name,
51
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
67
+ wrap_controlflow(
68
+ "controlflow.run",
69
+ version,
70
+ environment,
71
+ application_name,
72
+ tracer,
73
+ pricing_info,
74
+ capture_message_content,
75
+ metrics,
76
+ disable_metrics,
77
+ ),
52
78
  )
53
79
 
54
80
  def _uninstrument(self, **kwargs):
@@ -5,15 +5,29 @@ Module for monitoring controlflow.
5
5
 
6
6
  import logging
7
7
  from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
8
+ from opentelemetry.sdk.resources import (
9
+ SERVICE_NAME,
10
+ TELEMETRY_SDK_NAME,
11
+ DEPLOYMENT_ENVIRONMENT,
12
+ )
9
13
  from openlit.__helpers import handle_exception
10
14
  from openlit.semcov import SemanticConvention
11
15
 
12
16
  # Initialize logger for logging potential issues and operations
13
17
  logger = logging.getLogger(__name__)
14
18
 
15
- def wrap_controlflow(gen_ai_endpoint, version, environment, application_name,
16
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
19
+
20
+ def wrap_controlflow(
21
+ gen_ai_endpoint,
22
+ version,
23
+ environment,
24
+ application_name,
25
+ tracer,
26
+ pricing_info,
27
+ capture_message_content,
28
+ metrics,
29
+ disable_metrics,
30
+ ):
17
31
  """
18
32
  Creates a wrapper around a function call to trace and log its execution metrics.
19
33
 
@@ -55,48 +69,67 @@ def wrap_controlflow(gen_ai_endpoint, version, environment, application_name,
55
69
  errors are handled and logged appropriately.
56
70
  """
57
71
 
58
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
72
+ with tracer.start_as_current_span(
73
+ gen_ai_endpoint, kind=SpanKind.CLIENT
74
+ ) as span:
59
75
  response = wrapped(*args, **kwargs)
60
76
 
61
77
  try:
62
78
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
63
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
64
- gen_ai_endpoint)
65
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
66
- SemanticConvention.GEN_AI_SYSTEM_CONTROLFLOW)
67
- span.set_attribute(DEPLOYMENT_ENVIRONMENT,
68
- environment)
69
- span.set_attribute(SERVICE_NAME,
70
- application_name)
71
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
72
- SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT)
79
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
80
+ span.set_attribute(
81
+ SemanticConvention.GEN_AI_SYSTEM,
82
+ SemanticConvention.GEN_AI_SYSTEM_CONTROLFLOW,
83
+ )
84
+ span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
85
+ span.set_attribute(SERVICE_NAME, application_name)
86
+ span.set_attribute(
87
+ SemanticConvention.GEN_AI_OPERATION,
88
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
89
+ )
73
90
 
74
91
  if gen_ai_endpoint == "controlflow.create_agent":
75
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_ROLE,
76
- instance.name)
77
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_INSTRUCTIONS,
78
- kwargs.get("instructions", ""))
79
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_TOOLS,
80
- str(kwargs.get("tools", "")))
92
+ span.set_attribute(
93
+ SemanticConvention.GEN_AI_AGENT_ROLE, instance.name
94
+ )
95
+ span.set_attribute(
96
+ SemanticConvention.GEN_AI_AGENT_INSTRUCTIONS,
97
+ kwargs.get("instructions", ""),
98
+ )
99
+ span.set_attribute(
100
+ SemanticConvention.GEN_AI_AGENT_TOOLS,
101
+ str(kwargs.get("tools", "")),
102
+ )
81
103
 
82
104
  try:
83
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL,
84
- instance.model.model_name)
105
+ span.set_attribute(
106
+ SemanticConvention.GEN_AI_REQUEST_MODEL,
107
+ instance.model.model_name,
108
+ )
85
109
  except:
86
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL,
87
- kwargs.get("model", "openai/gpt-4o-mini"))
110
+ span.set_attribute(
111
+ SemanticConvention.GEN_AI_REQUEST_MODEL,
112
+ kwargs.get("model", "openai/gpt-4o-mini"),
113
+ )
88
114
 
89
115
  elif gen_ai_endpoint == "controlflow.create_task":
90
- if kwargs.get("objective","") == "":
91
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_GOAL,
92
- str(args[0]))
116
+ if kwargs.get("objective", "") == "":
117
+ span.set_attribute(
118
+ SemanticConvention.GEN_AI_AGENT_GOAL, str(args[0])
119
+ )
93
120
  else:
94
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_GOAL,
95
- kwargs.get("objective",""))
96
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_INSTRUCTIONS,
97
- kwargs.get("instructions", ""))
98
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_CONTEXT,
99
- str(kwargs.get("context", "")))
121
+ span.set_attribute(
122
+ SemanticConvention.GEN_AI_AGENT_GOAL,
123
+ kwargs.get("objective", ""),
124
+ )
125
+ span.set_attribute(
126
+ SemanticConvention.GEN_AI_AGENT_INSTRUCTIONS,
127
+ kwargs.get("instructions", ""),
128
+ )
129
+ span.set_attribute(
130
+ SemanticConvention.GEN_AI_AGENT_CONTEXT,
131
+ str(kwargs.get("context", "")),
132
+ )
100
133
 
101
134
  span.set_status(Status(StatusCode.OK))
102
135
 
@@ -6,15 +6,12 @@ import importlib.metadata
6
6
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
7
  from wrapt import wrap_function_wrapper
8
8
 
9
- from openlit.instrumentation.crawl4ai.crawl4ai import (
10
- wrap_crawl
11
- )
12
- from openlit.instrumentation.crawl4ai.async_crawl4ai import (
13
- async_wrap_crawl
14
- )
9
+ from openlit.instrumentation.crawl4ai.crawl4ai import wrap_crawl
10
+ from openlit.instrumentation.crawl4ai.async_crawl4ai import async_wrap_crawl
15
11
 
16
12
  _instruments = ("crawl4ai >= 0.4.0",)
17
13
 
14
+
18
15
  class Crawl4AIInstrumentor(BaseInstrumentor):
19
16
  """
20
17
  An instrumentor for crawl4ai's client library.
@@ -36,15 +33,33 @@ class Crawl4AIInstrumentor(BaseInstrumentor):
36
33
  wrap_function_wrapper(
37
34
  "crawl4ai.web_crawler",
38
35
  "WebCrawler.run",
39
- wrap_crawl("crawl4ai.web_crawl", version, environment, application_name,
40
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
36
+ wrap_crawl(
37
+ "crawl4ai.web_crawl",
38
+ version,
39
+ environment,
40
+ application_name,
41
+ tracer,
42
+ pricing_info,
43
+ capture_message_content,
44
+ metrics,
45
+ disable_metrics,
46
+ ),
41
47
  )
42
48
 
43
49
  wrap_function_wrapper(
44
50
  "crawl4ai.async_webcrawler",
45
51
  "AsyncWebCrawler.arun",
46
- async_wrap_crawl("crawl4ai.web_crawl", version, environment, application_name,
47
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
52
+ async_wrap_crawl(
53
+ "crawl4ai.web_crawl",
54
+ version,
55
+ environment,
56
+ application_name,
57
+ tracer,
58
+ pricing_info,
59
+ capture_message_content,
60
+ metrics,
61
+ disable_metrics,
62
+ ),
48
63
  )
49
64
 
50
65
  def _uninstrument(self, **kwargs):
@@ -5,7 +5,11 @@ Module for monitoring Crawl4AI calls.
5
5
 
6
6
  import logging
7
7
  from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
8
+ from opentelemetry.sdk.resources import (
9
+ SERVICE_NAME,
10
+ TELEMETRY_SDK_NAME,
11
+ DEPLOYMENT_ENVIRONMENT,
12
+ )
9
13
  from openlit.__helpers import (
10
14
  handle_exception,
11
15
  )
@@ -14,8 +18,18 @@ from openlit.semcov import SemanticConvention
14
18
  # Initialize logger for logging potential issues and operations
15
19
  logger = logging.getLogger(__name__)
16
20
 
17
- def async_wrap_crawl(gen_ai_endpoint, version, environment, application_name,
18
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
21
+
22
+ def async_wrap_crawl(
23
+ gen_ai_endpoint,
24
+ version,
25
+ environment,
26
+ application_name,
27
+ tracer,
28
+ pricing_info,
29
+ capture_message_content,
30
+ metrics,
31
+ disable_metrics,
32
+ ):
19
33
  """
20
34
  Generates a telemetry wrapper for chat completions to collect metrics.
21
35
 
@@ -50,44 +64,77 @@ def async_wrap_crawl(gen_ai_endpoint, version, environment, application_name,
50
64
  """
51
65
 
52
66
  # pylint: disable=line-too-long
53
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
67
+ with tracer.start_as_current_span(
68
+ gen_ai_endpoint, kind=SpanKind.CLIENT
69
+ ) as span:
54
70
  response = await wrapped(*args, **kwargs)
55
71
 
56
72
  try:
57
73
  # Set base span attribues
58
74
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
59
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
60
- SemanticConvention.GEN_AI_SYSTEM_CRAWL4AI)
61
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
62
- SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT)
63
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
64
- gen_ai_endpoint)
65
- span.set_attribute(SERVICE_NAME,
66
- application_name)
67
- span.set_attribute(DEPLOYMENT_ENVIRONMENT,
68
- environment)
69
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_TYPE,
70
- SemanticConvention.GEN_AI_AGENT_TYPE_BROWSER)
71
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_ENABLE_CACHE, not kwargs.get("disable_cache", False))
72
-
73
- url = kwargs.get("url") if "url" in kwargs else str(args[0]) if args else None
75
+ span.set_attribute(
76
+ SemanticConvention.GEN_AI_SYSTEM,
77
+ SemanticConvention.GEN_AI_SYSTEM_CRAWL4AI,
78
+ )
79
+ span.set_attribute(
80
+ SemanticConvention.GEN_AI_OPERATION,
81
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
82
+ )
83
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
84
+ span.set_attribute(SERVICE_NAME, application_name)
85
+ span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
86
+ span.set_attribute(
87
+ SemanticConvention.GEN_AI_AGENT_TYPE,
88
+ SemanticConvention.GEN_AI_AGENT_TYPE_BROWSER,
89
+ )
90
+ span.set_attribute(
91
+ SemanticConvention.GEN_AI_AGENT_ENABLE_CACHE,
92
+ not kwargs.get("disable_cache", False),
93
+ )
94
+
95
+ url = (
96
+ kwargs.get("url")
97
+ if "url" in kwargs
98
+ else str(args[0])
99
+ if args
100
+ else None
101
+ )
74
102
  if url is not None:
75
103
  span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL, url)
76
104
 
77
- extraction_strategy = kwargs.get("extraction_strategy", "NoExtractionStrategy")
78
- extraction_name = extraction_strategy.name if hasattr(extraction_strategy, 'name') else extraction_strategy
79
-
80
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_STRATEGY, extraction_name)
81
-
82
- if extraction_name == "LLMExtractionStrategy" and hasattr(extraction_strategy, 'provider'):
83
- _, llm_model = extraction_strategy.provider.split('/')
84
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, llm_model)
105
+ extraction_strategy = kwargs.get(
106
+ "extraction_strategy", "NoExtractionStrategy"
107
+ )
108
+ extraction_name = (
109
+ extraction_strategy.name
110
+ if hasattr(extraction_strategy, "name")
111
+ else extraction_strategy
112
+ )
113
+
114
+ span.set_attribute(
115
+ SemanticConvention.GEN_AI_AGENT_STRATEGY, extraction_name
116
+ )
117
+
118
+ if extraction_name == "LLMExtractionStrategy" and hasattr(
119
+ extraction_strategy, "provider"
120
+ ):
121
+ _, llm_model = extraction_strategy.provider.split("/")
122
+ span.set_attribute(
123
+ SemanticConvention.GEN_AI_REQUEST_MODEL, llm_model
124
+ )
85
125
 
86
126
  elif extraction_name == "CosineStrategy":
87
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, "all-MiniLM-L6-v2")
88
-
89
- elif extraction_name == "JsonCssExtractionStrategy" and hasattr(extraction_strategy, 'schema'):
90
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_SCHEMA, str(extraction_strategy.schema))
127
+ span.set_attribute(
128
+ SemanticConvention.GEN_AI_REQUEST_MODEL, "all-MiniLM-L6-v2"
129
+ )
130
+
131
+ elif extraction_name == "JsonCssExtractionStrategy" and hasattr(
132
+ extraction_strategy, "schema"
133
+ ):
134
+ span.set_attribute(
135
+ SemanticConvention.GEN_AI_AGENT_SCHEMA,
136
+ str(extraction_strategy.schema),
137
+ )
91
138
 
92
139
  span.set_status(Status(StatusCode.OK))
93
140
 
@@ -5,7 +5,11 @@ Module for monitoring Crawl4AI calls.
5
5
 
6
6
  import logging
7
7
  from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
8
+ from opentelemetry.sdk.resources import (
9
+ SERVICE_NAME,
10
+ TELEMETRY_SDK_NAME,
11
+ DEPLOYMENT_ENVIRONMENT,
12
+ )
9
13
  from openlit.__helpers import (
10
14
  handle_exception,
11
15
  )
@@ -14,8 +18,18 @@ from openlit.semcov import SemanticConvention
14
18
  # Initialize logger for logging potential issues and operations
15
19
  logger = logging.getLogger(__name__)
16
20
 
17
- def wrap_crawl(gen_ai_endpoint, version, environment, application_name,
18
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
21
+
22
+ def wrap_crawl(
23
+ gen_ai_endpoint,
24
+ version,
25
+ environment,
26
+ application_name,
27
+ tracer,
28
+ pricing_info,
29
+ capture_message_content,
30
+ metrics,
31
+ disable_metrics,
32
+ ):
19
33
  """
20
34
  Generates a telemetry wrapper for chat completions to collect metrics.
21
35
 
@@ -50,44 +64,77 @@ def wrap_crawl(gen_ai_endpoint, version, environment, application_name,
50
64
  """
51
65
 
52
66
  # pylint: disable=line-too-long
53
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
67
+ with tracer.start_as_current_span(
68
+ gen_ai_endpoint, kind=SpanKind.CLIENT
69
+ ) as span:
54
70
  response = wrapped(*args, **kwargs)
55
71
 
56
72
  try:
57
73
  # Set base span attribues
58
74
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
59
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
60
- SemanticConvention.GEN_AI_SYSTEM_CRAWL4AI)
61
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
62
- SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT)
63
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
64
- gen_ai_endpoint)
65
- span.set_attribute(SERVICE_NAME,
66
- application_name)
67
- span.set_attribute(DEPLOYMENT_ENVIRONMENT,
68
- environment)
69
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_TYPE,
70
- SemanticConvention.GEN_AI_AGENT_TYPE_BROWSER)
71
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_ENABLE_CACHE, not kwargs.get("disable_cache", False))
72
-
73
- url = kwargs.get("url") if "url" in kwargs else str(args[0]) if args else None
75
+ span.set_attribute(
76
+ SemanticConvention.GEN_AI_SYSTEM,
77
+ SemanticConvention.GEN_AI_SYSTEM_CRAWL4AI,
78
+ )
79
+ span.set_attribute(
80
+ SemanticConvention.GEN_AI_OPERATION,
81
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
82
+ )
83
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
84
+ span.set_attribute(SERVICE_NAME, application_name)
85
+ span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
86
+ span.set_attribute(
87
+ SemanticConvention.GEN_AI_AGENT_TYPE,
88
+ SemanticConvention.GEN_AI_AGENT_TYPE_BROWSER,
89
+ )
90
+ span.set_attribute(
91
+ SemanticConvention.GEN_AI_AGENT_ENABLE_CACHE,
92
+ not kwargs.get("disable_cache", False),
93
+ )
94
+
95
+ url = (
96
+ kwargs.get("url")
97
+ if "url" in kwargs
98
+ else str(args[0])
99
+ if args
100
+ else None
101
+ )
74
102
  if url is not None:
75
103
  span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL, url)
76
104
 
77
- extraction_strategy = kwargs.get("extraction_strategy", "NoExtractionStrategy")
78
- extraction_name = extraction_strategy.name if hasattr(extraction_strategy, 'name') else extraction_strategy
79
-
80
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_STRATEGY, extraction_name)
81
-
82
- if extraction_name == "LLMExtractionStrategy" and hasattr(extraction_strategy, 'provider'):
83
- _, llm_model = extraction_strategy.provider.split('/')
84
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, llm_model)
105
+ extraction_strategy = kwargs.get(
106
+ "extraction_strategy", "NoExtractionStrategy"
107
+ )
108
+ extraction_name = (
109
+ extraction_strategy.name
110
+ if hasattr(extraction_strategy, "name")
111
+ else extraction_strategy
112
+ )
113
+
114
+ span.set_attribute(
115
+ SemanticConvention.GEN_AI_AGENT_STRATEGY, extraction_name
116
+ )
117
+
118
+ if extraction_name == "LLMExtractionStrategy" and hasattr(
119
+ extraction_strategy, "provider"
120
+ ):
121
+ _, llm_model = extraction_strategy.provider.split("/")
122
+ span.set_attribute(
123
+ SemanticConvention.GEN_AI_REQUEST_MODEL, llm_model
124
+ )
85
125
 
86
126
  elif extraction_name == "CosineStrategy":
87
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, "all-MiniLM-L6-v2")
88
-
89
- elif extraction_name == "JsonCssExtractionStrategy" and hasattr(extraction_strategy, 'schema'):
90
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_SCHEMA, str(extraction_strategy.schema))
127
+ span.set_attribute(
128
+ SemanticConvention.GEN_AI_REQUEST_MODEL, "all-MiniLM-L6-v2"
129
+ )
130
+
131
+ elif extraction_name == "JsonCssExtractionStrategy" and hasattr(
132
+ extraction_strategy, "schema"
133
+ ):
134
+ span.set_attribute(
135
+ SemanticConvention.GEN_AI_AGENT_SCHEMA,
136
+ str(extraction_strategy.schema),
137
+ )
91
138
 
92
139
  span.set_status(Status(StatusCode.OK))
93
140
 
@@ -19,7 +19,6 @@ WORKFLOW_OPERATIONS = [
19
19
  ("crewai.crew", "Crew.kickoff_async", "crew_kickoff_async"),
20
20
  ("crewai.crew", "Crew.kickoff_for_each", "crew_kickoff_for_each"),
21
21
  ("crewai.crew", "Crew.kickoff_for_each_async", "crew_kickoff_for_each_async"),
22
-
23
22
  # High-level Agent and Task Operations
24
23
  ("crewai.agent", "Agent.execute_task", "agent_execute_task"),
25
24
  ("crewai.task", "Task.execute", "task_execute"),
@@ -33,19 +32,18 @@ COMPONENT_OPERATIONS = [
33
32
  ("crewai.tools.base", "BaseTool._run", "tool_run_internal"),
34
33
  ("crewai.memory.base", "BaseMemory.save", "memory_save"),
35
34
  ("crewai.memory.base", "BaseMemory.search", "memory_search"),
36
-
37
35
  # Process and Collaboration Operations
38
36
  ("crewai.process", "Process.kickoff", "process_kickoff"),
39
37
  ("crewai.agent", "Agent.delegate", "agent_delegate"),
40
38
  ("crewai.agent", "Agent.ask_question", "agent_ask_question"),
41
39
  ("crewai.task", "Task.callback", "task_callback"),
42
-
43
40
  # Internal Task Management
44
41
  # Instrument only the core task execution (remove the sync duplicate)
45
42
  # Task Operations (keep only core execution)
46
43
  ("crewai.task", "Task._execute_core", "task_execute_core"),
47
44
  ]
48
45
 
46
+
49
47
  class CrewAIInstrumentor(BaseInstrumentor):
50
48
  """
51
49
  Modern instrumentor for CrewAI framework with comprehensive coverage.
@@ -70,10 +68,19 @@ class CrewAIInstrumentor(BaseInstrumentor):
70
68
  for module, method, operation_type in WORKFLOW_OPERATIONS:
71
69
  try:
72
70
  wrap_function_wrapper(
73
- module, method,
74
- general_wrap(operation_type, version, environment, application_name,
75
- tracer, pricing_info, capture_message_content,
76
- metrics, disable_metrics)
71
+ module,
72
+ method,
73
+ general_wrap(
74
+ operation_type,
75
+ version,
76
+ environment,
77
+ application_name,
78
+ tracer,
79
+ pricing_info,
80
+ capture_message_content,
81
+ metrics,
82
+ disable_metrics,
83
+ ),
77
84
  )
78
85
  except Exception:
79
86
  # Graceful degradation for missing operations
@@ -84,10 +91,19 @@ class CrewAIInstrumentor(BaseInstrumentor):
84
91
  if "async" in operation_type:
85
92
  try:
86
93
  wrap_function_wrapper(
87
- module, method,
88
- async_general_wrap(operation_type, version, environment,
89
- application_name, tracer, pricing_info,
90
- capture_message_content, metrics, disable_metrics)
94
+ module,
95
+ method,
96
+ async_general_wrap(
97
+ operation_type,
98
+ version,
99
+ environment,
100
+ application_name,
101
+ tracer,
102
+ pricing_info,
103
+ capture_message_content,
104
+ metrics,
105
+ disable_metrics,
106
+ ),
91
107
  )
92
108
  except Exception:
93
109
  pass
@@ -97,10 +113,19 @@ class CrewAIInstrumentor(BaseInstrumentor):
97
113
  for module, method, operation_type in COMPONENT_OPERATIONS:
98
114
  try:
99
115
  wrap_function_wrapper(
100
- module, method,
101
- general_wrap(operation_type, version, environment,
102
- application_name, tracer, pricing_info,
103
- capture_message_content, metrics, disable_metrics)
116
+ module,
117
+ method,
118
+ general_wrap(
119
+ operation_type,
120
+ version,
121
+ environment,
122
+ application_name,
123
+ tracer,
124
+ pricing_info,
125
+ capture_message_content,
126
+ metrics,
127
+ disable_metrics,
128
+ ),
104
129
  )
105
130
  except Exception:
106
131
  pass