openlit 1.34.30__py3-none-any.whl → 1.34.32__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.
- openlit/__helpers.py +235 -86
- openlit/__init__.py +19 -14
- openlit/_instrumentors.py +2 -1
- openlit/evals/all.py +50 -21
- openlit/evals/bias_detection.py +47 -20
- openlit/evals/hallucination.py +53 -22
- openlit/evals/toxicity.py +50 -21
- openlit/evals/utils.py +54 -30
- openlit/guard/all.py +61 -19
- openlit/guard/prompt_injection.py +34 -14
- openlit/guard/restrict_topic.py +46 -15
- openlit/guard/sensitive_topic.py +34 -14
- openlit/guard/utils.py +58 -22
- openlit/instrumentation/ag2/__init__.py +113 -6
- openlit/instrumentation/ag2/ag2.py +459 -17
- openlit/instrumentation/ag2/async_ag2.py +459 -17
- openlit/instrumentation/ag2/utils.py +475 -31
- openlit/instrumentation/ai21/__init__.py +43 -14
- openlit/instrumentation/ai21/ai21.py +47 -21
- openlit/instrumentation/ai21/async_ai21.py +47 -21
- openlit/instrumentation/ai21/utils.py +299 -78
- openlit/instrumentation/anthropic/__init__.py +21 -4
- openlit/instrumentation/anthropic/anthropic.py +28 -17
- openlit/instrumentation/anthropic/async_anthropic.py +28 -17
- openlit/instrumentation/anthropic/utils.py +145 -35
- openlit/instrumentation/assemblyai/__init__.py +11 -2
- openlit/instrumentation/assemblyai/assemblyai.py +15 -4
- openlit/instrumentation/assemblyai/utils.py +120 -25
- openlit/instrumentation/astra/__init__.py +43 -10
- openlit/instrumentation/astra/astra.py +28 -5
- openlit/instrumentation/astra/async_astra.py +28 -5
- openlit/instrumentation/astra/utils.py +151 -55
- openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
- openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
- openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
- openlit/instrumentation/azure_ai_inference/utils.py +307 -83
- openlit/instrumentation/bedrock/__init__.py +21 -4
- openlit/instrumentation/bedrock/bedrock.py +63 -25
- openlit/instrumentation/bedrock/utils.py +139 -30
- openlit/instrumentation/chroma/__init__.py +89 -16
- openlit/instrumentation/chroma/chroma.py +28 -6
- openlit/instrumentation/chroma/utils.py +167 -51
- openlit/instrumentation/cohere/__init__.py +63 -18
- openlit/instrumentation/cohere/async_cohere.py +63 -24
- openlit/instrumentation/cohere/cohere.py +63 -24
- openlit/instrumentation/cohere/utils.py +286 -73
- openlit/instrumentation/controlflow/__init__.py +35 -9
- openlit/instrumentation/controlflow/controlflow.py +66 -33
- openlit/instrumentation/crawl4ai/__init__.py +25 -10
- openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
- openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
- openlit/instrumentation/crewai/__init__.py +40 -15
- openlit/instrumentation/crewai/async_crewai.py +32 -7
- openlit/instrumentation/crewai/crewai.py +32 -7
- openlit/instrumentation/crewai/utils.py +159 -56
- openlit/instrumentation/dynamiq/__init__.py +46 -12
- openlit/instrumentation/dynamiq/dynamiq.py +74 -33
- openlit/instrumentation/elevenlabs/__init__.py +23 -4
- openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
- openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
- openlit/instrumentation/elevenlabs/utils.py +128 -25
- openlit/instrumentation/embedchain/__init__.py +11 -2
- openlit/instrumentation/embedchain/embedchain.py +68 -35
- openlit/instrumentation/firecrawl/__init__.py +24 -7
- openlit/instrumentation/firecrawl/firecrawl.py +46 -20
- openlit/instrumentation/google_ai_studio/__init__.py +45 -10
- openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
- openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
- openlit/instrumentation/google_ai_studio/utils.py +180 -67
- openlit/instrumentation/gpt4all/__init__.py +22 -7
- openlit/instrumentation/gpt4all/gpt4all.py +67 -29
- openlit/instrumentation/gpt4all/utils.py +285 -61
- openlit/instrumentation/gpu/__init__.py +128 -47
- openlit/instrumentation/groq/__init__.py +21 -4
- openlit/instrumentation/groq/async_groq.py +33 -21
- openlit/instrumentation/groq/groq.py +33 -21
- openlit/instrumentation/groq/utils.py +192 -55
- openlit/instrumentation/haystack/__init__.py +70 -24
- openlit/instrumentation/haystack/async_haystack.py +28 -6
- openlit/instrumentation/haystack/haystack.py +28 -6
- openlit/instrumentation/haystack/utils.py +196 -74
- openlit/instrumentation/julep/__init__.py +69 -19
- openlit/instrumentation/julep/async_julep.py +53 -27
- openlit/instrumentation/julep/julep.py +53 -28
- openlit/instrumentation/langchain/__init__.py +74 -63
- openlit/instrumentation/langchain/callback_handler.py +1100 -0
- openlit/instrumentation/langchain_community/__init__.py +13 -2
- openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
- openlit/instrumentation/langchain_community/langchain_community.py +23 -5
- openlit/instrumentation/langchain_community/utils.py +35 -9
- openlit/instrumentation/letta/__init__.py +68 -15
- openlit/instrumentation/letta/letta.py +99 -54
- openlit/instrumentation/litellm/__init__.py +43 -14
- openlit/instrumentation/litellm/async_litellm.py +51 -26
- openlit/instrumentation/litellm/litellm.py +51 -26
- openlit/instrumentation/litellm/utils.py +304 -102
- openlit/instrumentation/llamaindex/__init__.py +267 -90
- openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
- openlit/instrumentation/llamaindex/llamaindex.py +28 -6
- openlit/instrumentation/llamaindex/utils.py +204 -91
- openlit/instrumentation/mem0/__init__.py +11 -2
- openlit/instrumentation/mem0/mem0.py +50 -29
- openlit/instrumentation/milvus/__init__.py +10 -2
- openlit/instrumentation/milvus/milvus.py +31 -6
- openlit/instrumentation/milvus/utils.py +166 -67
- openlit/instrumentation/mistral/__init__.py +63 -18
- openlit/instrumentation/mistral/async_mistral.py +63 -24
- openlit/instrumentation/mistral/mistral.py +63 -24
- openlit/instrumentation/mistral/utils.py +277 -69
- openlit/instrumentation/multion/__init__.py +69 -19
- openlit/instrumentation/multion/async_multion.py +57 -26
- openlit/instrumentation/multion/multion.py +57 -26
- openlit/instrumentation/ollama/__init__.py +39 -18
- openlit/instrumentation/ollama/async_ollama.py +57 -26
- openlit/instrumentation/ollama/ollama.py +57 -26
- openlit/instrumentation/ollama/utils.py +226 -50
- openlit/instrumentation/openai/__init__.py +156 -32
- openlit/instrumentation/openai/async_openai.py +147 -67
- openlit/instrumentation/openai/openai.py +150 -67
- openlit/instrumentation/openai/utils.py +657 -185
- openlit/instrumentation/openai_agents/__init__.py +5 -1
- openlit/instrumentation/openai_agents/processor.py +110 -90
- openlit/instrumentation/phidata/__init__.py +13 -5
- openlit/instrumentation/phidata/phidata.py +67 -32
- openlit/instrumentation/pinecone/__init__.py +48 -9
- openlit/instrumentation/pinecone/async_pinecone.py +27 -5
- openlit/instrumentation/pinecone/pinecone.py +27 -5
- openlit/instrumentation/pinecone/utils.py +153 -47
- openlit/instrumentation/premai/__init__.py +22 -7
- openlit/instrumentation/premai/premai.py +51 -26
- openlit/instrumentation/premai/utils.py +246 -59
- openlit/instrumentation/pydantic_ai/__init__.py +49 -22
- openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
- openlit/instrumentation/pydantic_ai/utils.py +89 -24
- openlit/instrumentation/qdrant/__init__.py +19 -4
- openlit/instrumentation/qdrant/async_qdrant.py +33 -7
- openlit/instrumentation/qdrant/qdrant.py +33 -7
- openlit/instrumentation/qdrant/utils.py +228 -93
- openlit/instrumentation/reka/__init__.py +23 -10
- openlit/instrumentation/reka/async_reka.py +17 -11
- openlit/instrumentation/reka/reka.py +17 -11
- openlit/instrumentation/reka/utils.py +138 -36
- openlit/instrumentation/together/__init__.py +44 -12
- openlit/instrumentation/together/async_together.py +50 -27
- openlit/instrumentation/together/together.py +50 -27
- openlit/instrumentation/together/utils.py +301 -71
- openlit/instrumentation/transformers/__init__.py +2 -1
- openlit/instrumentation/transformers/transformers.py +13 -3
- openlit/instrumentation/transformers/utils.py +139 -36
- openlit/instrumentation/vertexai/__init__.py +81 -16
- openlit/instrumentation/vertexai/async_vertexai.py +33 -15
- openlit/instrumentation/vertexai/utils.py +123 -27
- openlit/instrumentation/vertexai/vertexai.py +33 -15
- openlit/instrumentation/vllm/__init__.py +12 -5
- openlit/instrumentation/vllm/utils.py +121 -31
- openlit/instrumentation/vllm/vllm.py +16 -10
- openlit/otel/events.py +35 -10
- openlit/otel/metrics.py +32 -24
- openlit/otel/tracing.py +24 -9
- openlit/semcov/__init__.py +82 -6
- {openlit-1.34.30.dist-info → openlit-1.34.32.dist-info}/METADATA +2 -1
- openlit-1.34.32.dist-info/RECORD +166 -0
- openlit/instrumentation/langchain/async_langchain.py +0 -102
- openlit/instrumentation/langchain/langchain.py +0 -102
- openlit/instrumentation/langchain/utils.py +0 -252
- openlit-1.34.30.dist-info/RECORD +0 -168
- {openlit-1.34.30.dist-info → openlit-1.34.32.dist-info}/LICENSE +0 -0
- {openlit-1.34.30.dist-info → openlit-1.34.32.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(
|
37
|
-
|
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(
|
44
|
-
|
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(
|
51
|
-
|
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
|
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
|
-
|
16
|
-
|
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(
|
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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
span.set_attribute(SERVICE_NAME,
|
70
|
-
|
71
|
-
|
72
|
-
|
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(
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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(
|
84
|
-
|
105
|
+
span.set_attribute(
|
106
|
+
SemanticConvention.GEN_AI_REQUEST_MODEL,
|
107
|
+
instance.model.model_name,
|
108
|
+
)
|
85
109
|
except:
|
86
|
-
span.set_attribute(
|
87
|
-
|
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(
|
92
|
-
|
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(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
span.set_attribute(
|
99
|
-
|
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
|
-
|
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(
|
40
|
-
|
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(
|
47
|
-
|
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
|
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
|
-
|
18
|
-
|
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(
|
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(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
span.set_attribute(
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
span.set_attribute(
|
68
|
-
|
69
|
-
span.set_attribute(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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(
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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(
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
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
|
-
|
18
|
-
|
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(
|
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(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
span.set_attribute(
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
span.set_attribute(
|
68
|
-
|
69
|
-
span.set_attribute(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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(
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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(
|
88
|
-
|
89
|
-
|
90
|
-
|
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,
|
74
|
-
|
75
|
-
|
76
|
-
|
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,
|
88
|
-
|
89
|
-
|
90
|
-
|
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,
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|