openlit 1.34.22__py3-none-any.whl → 1.34.24__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 CHANGED
@@ -205,11 +205,22 @@ def set_server_address_and_port(client_instance: Any,
205
205
  config = getattr(client_instance, 'sdk_configuration', None)
206
206
  base_url = getattr(config, 'server_url', None)
207
207
 
208
+ if not base_url:
209
+ # Attempt to get host from instance.config.host (used by Pinecone and other vector DBs)
210
+ config = getattr(client_instance, 'config', None)
211
+ base_url = getattr(config, 'host', None)
212
+
208
213
  if base_url:
209
214
  if isinstance(base_url, str):
210
- url = urlparse(base_url)
211
- server_address = url.hostname or default_server_address
212
- server_port = url.port if url.port is not None else default_server_port
215
+ # Check if it's a full URL or just a hostname
216
+ if base_url.startswith(('http://', 'https://')):
217
+ url = urlparse(base_url)
218
+ server_address = url.hostname or default_server_address
219
+ server_port = url.port if url.port is not None else default_server_port
220
+ else:
221
+ # If it's just a hostname (like Pinecone's case), use it directly
222
+ server_address = base_url
223
+ server_port = default_server_port
213
224
  else: # base_url might not be a str; handle as an object.
214
225
  server_address = getattr(base_url, 'host', None) or default_server_address
215
226
  port_attr = getattr(base_url, 'port', None)
@@ -442,3 +453,37 @@ def record_image_metrics(metrics, gen_ai_operation, gen_ai_system, server_addres
442
453
  metrics["genai_client_operation_duration"].record(end_time - start_time, attributes)
443
454
  metrics["genai_requests"].add(1, attributes)
444
455
  metrics["genai_cost"].record(cost, attributes)
456
+
457
+ def common_db_span_attributes(scope, db_system, server_address, server_port,
458
+ environment, application_name, version):
459
+ """
460
+ Set common span attributes for database operations.
461
+ """
462
+
463
+ scope._span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
464
+ scope._span.set_attribute(SemanticConvention.GEN_AI_OPERATION, SemanticConvention.GEN_AI_OPERATION_TYPE_VECTORDB)
465
+ scope._span.set_attribute(SemanticConvention.DB_SYSTEM_NAME, db_system)
466
+ scope._span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
467
+ scope._span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
468
+ scope._span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
469
+ scope._span.set_attribute(SERVICE_NAME, application_name)
470
+ scope._span.set_attribute(SemanticConvention.DB_SDK_VERSION, version)
471
+
472
+ def record_db_metrics(metrics, db_system, server_address, server_port,
473
+ environment, application_name, start_time, end_time):
474
+ """
475
+ Record database-specific metrics for the operation.
476
+ """
477
+
478
+ attributes = create_metrics_attributes(
479
+ operation=SemanticConvention.GEN_AI_OPERATION_TYPE_VECTORDB,
480
+ system=db_system,
481
+ request_model=db_system,
482
+ server_address=server_address,
483
+ server_port=server_port,
484
+ response_model=db_system,
485
+ service_name=application_name,
486
+ deployment_environment=environment,
487
+ )
488
+ metrics["db_requests"].add(1, attributes)
489
+ metrics["db_client_operation_duration"].record(end_time - start_time, attributes)
openlit/__init__.py CHANGED
@@ -42,6 +42,7 @@ from openlit.instrumentation.premai import PremAIInstrumentor
42
42
  from openlit.instrumentation.assemblyai import AssemblyAIInstrumentor
43
43
  from openlit.instrumentation.azure_ai_inference import AzureAIInferenceInstrumentor
44
44
  from openlit.instrumentation.langchain import LangChainInstrumentor
45
+ from openlit.instrumentation.langchain_community import LangChainCommunityInstrumentor
45
46
  from openlit.instrumentation.llamaindex import LlamaIndexInstrumentor
46
47
  from openlit.instrumentation.haystack import HaystackInstrumentor
47
48
  from openlit.instrumentation.embedchain import EmbedChainInstrumentor
@@ -267,6 +268,7 @@ def init(
267
268
  "google-ai-studio": "google.genai",
268
269
  "azure-ai-inference": "azure.ai.inference",
269
270
  "langchain": "langchain",
271
+ "langchain_community": "langchain_community",
270
272
  "llama_index": "llama_index",
271
273
  "haystack": "haystack",
272
274
  "embedchain": "embedchain",
@@ -387,6 +389,7 @@ def init(
387
389
  "google-ai-studio": GoogleAIStudioInstrumentor(),
388
390
  "azure-ai-inference": AzureAIInferenceInstrumentor(),
389
391
  "langchain": LangChainInstrumentor(),
392
+ "langchain_community": LangChainCommunityInstrumentor(),
390
393
  "llama_index": LlamaIndexInstrumentor(),
391
394
  "haystack": HaystackInstrumentor(),
392
395
  "embedchain": EmbedChainInstrumentor(),
@@ -8,40 +8,44 @@ from wrapt import wrap_function_wrapper
8
8
  from openlit.instrumentation.ag2.ag2 import (
9
9
  conversable_agent, agent_run
10
10
  )
11
+ from openlit.instrumentation.ag2.async_ag2 import (
12
+ async_conversable_agent, async_agent_run
13
+ )
11
14
 
12
- _instruments = ('ag2 >= 0.3.2',)
15
+ _instruments = ("ag2 >= 0.3.2",)
13
16
 
14
17
  class AG2Instrumentor(BaseInstrumentor):
15
18
  """
16
- An instrumentor for AG2's client library.
19
+ An instrumentor for AG2 client library.
17
20
  """
18
21
 
19
22
  def instrumentation_dependencies(self) -> Collection[str]:
20
23
  return _instruments
21
24
 
22
25
  def _instrument(self, **kwargs):
23
- application_name = kwargs.get('application_name', 'default_application')
24
- environment = kwargs.get('environment', 'default_environment')
25
- tracer = kwargs.get('tracer')
26
- event_provider = kwargs.get('event_provider')
27
- metrics = kwargs.get('metrics_dict')
28
- pricing_info = kwargs.get('pricing_info', {})
29
- capture_message_content = kwargs.get('capture_message_content', False)
30
- disable_metrics = kwargs.get('disable_metrics')
31
- version = importlib.metadata.version('ag2')
32
-
26
+ version = importlib.metadata.version("ag2")
27
+ environment = kwargs.get("environment", "default")
28
+ application_name = kwargs.get("application_name", "default")
29
+ tracer = kwargs.get("tracer")
30
+ pricing_info = kwargs.get("pricing_info", {})
31
+ capture_message_content = kwargs.get("capture_message_content", False)
32
+ metrics = kwargs.get("metrics_dict")
33
+ disable_metrics = kwargs.get("disable_metrics")
34
+
35
+ # sync conversable agent
33
36
  wrap_function_wrapper(
34
- 'autogen.agentchat.conversable_agent',
35
- 'ConversableAgent.__init__',
37
+ "autogen.agentchat.conversable_agent",
38
+ "ConversableAgent.__init__",
36
39
  conversable_agent(version, environment, application_name,
37
- tracer, event_provider, pricing_info, capture_message_content, metrics, disable_metrics),
40
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics),
38
41
  )
39
42
 
43
+ # sync agent run
40
44
  wrap_function_wrapper(
41
- 'autogen.agentchat.conversable_agent',
42
- 'ConversableAgent.run',
45
+ "autogen.agentchat.conversable_agent",
46
+ "ConversableAgent.run",
43
47
  agent_run(version, environment, application_name,
44
- tracer, event_provider, pricing_info, capture_message_content, metrics, disable_metrics),
48
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics),
45
49
  )
46
50
 
47
51
  def _uninstrument(self, **kwargs):
@@ -2,162 +2,113 @@
2
2
  Module for monitoring AG2 API calls.
3
3
  """
4
4
 
5
- import logging
6
5
  import time
7
- from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
6
+ from opentelemetry.trace import SpanKind
9
7
  from openlit.__helpers import (
10
8
  handle_exception,
11
- get_chat_model_cost,
12
- otel_event,
9
+ set_server_address_and_port
10
+ )
11
+ from openlit.instrumentation.ag2.utils import (
12
+ process_agent_creation,
13
+ process_agent_run,
13
14
  )
14
15
  from openlit.semcov import SemanticConvention
15
16
 
16
- # Initialize logger for logging potential issues and operations
17
- logger = logging.getLogger(__name__)
18
-
19
- AGENT_NAME = ''
20
- REQUEST_MODEL = ''
21
- SYSTEM_MESSAGE = ''
22
- MODEL_AND_NAME_SET = False
23
-
24
- def set_span_attributes(span, version, operation_name, environment,
25
- application_name, server_address, server_port, request_model):
26
- """
27
- Set common attributes for the span.
28
- """
29
-
30
- # Set Span attributes (OTel Semconv)
31
- span.set_attribute(TELEMETRY_SDK_NAME, 'openlit')
32
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION, operation_name)
33
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, SemanticConvention.GEN_AI_SYSTEM_AG2)
34
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_NAME, AGENT_NAME)
35
- span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
36
- span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
37
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
38
-
39
- # Set Span attributes (Extras)
40
- span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
41
- span.set_attribute(SERVICE_NAME, application_name)
42
- span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
43
-
44
- def calculate_tokens_and_cost(response, request_model, pricing_info):
17
+ def conversable_agent(version, environment, application_name, tracer, pricing_info,
18
+ capture_message_content, metrics, disable_metrics):
45
19
  """
46
- Calculate the input, output tokens, and their respective costs.
20
+ Generates a telemetry wrapper for AG2 conversable agent creation.
47
21
  """
48
- input_tokens = 0
49
- output_tokens = 0
50
22
 
51
- for usage_data in response.cost.values():
52
- if isinstance(usage_data, dict):
53
- for model_data in usage_data.values():
54
- if isinstance(model_data, dict):
55
- input_tokens += model_data.get('prompt_tokens', 0)
56
- output_tokens += model_data.get('completion_tokens', 0)
57
-
58
- cost = get_chat_model_cost(request_model, pricing_info, input_tokens, output_tokens)
59
- return input_tokens, output_tokens, cost
60
-
61
- def emit_events(response, event_provider, capture_message_content):
62
- """
63
- Emit OpenTelemetry events for each chat history entry.
64
- """
65
- for chat in response.chat_history:
66
- event_type = (
67
- SemanticConvention.GEN_AI_CHOICE if chat['role'] == 'user'
68
- else SemanticConvention.GEN_AI_USER_MESSAGE
69
- )
70
- choice_event = otel_event(
71
- name=event_type,
72
- attributes={
73
- SemanticConvention.GEN_AI_SYSTEM: SemanticConvention.GEN_AI_SYSTEM_AG2
74
- },
75
- body={
76
- 'index': response.chat_history.index(chat),
77
- 'message': {
78
- **({'content': chat['content']} if capture_message_content else {}),
79
- 'role': 'assistant' if chat['role'] == 'user' else 'user'
80
- }
81
- }
82
- )
83
- event_provider.emit(choice_event)
84
-
85
- def conversable_agent(version, environment, application_name,
86
- tracer, event_provider, pricing_info, capture_message_content, metrics, disable_metrics):
87
- """
88
- Generates a telemetry wrapper for GenAI function call
89
- """
90
23
  def wrapper(wrapped, instance, args, kwargs):
91
- server_address, server_port = '127.0.0.1', 80
92
- global AGENT_NAME, MODEL_AND_NAME_SET, REQUEST_MODEL, SYSTEM_MESSAGE
24
+ """
25
+ Wraps the AG2 conversable agent creation call.
26
+ """
93
27
 
94
- if not MODEL_AND_NAME_SET:
95
- AGENT_NAME = kwargs.get('name', 'NOT_FOUND')
96
- REQUEST_MODEL = kwargs.get('llm_config', {}).get('model', 'gpt-4o')
97
- SYSTEM_MESSAGE = kwargs.get('system_message', '')
98
- MODEL_AND_NAME_SET = True
28
+ server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 80)
29
+ agent_name = kwargs.get("name", "NOT_FOUND")
30
+ llm_config = kwargs.get("llm_config", {})
31
+ system_message = kwargs.get("system_message", "")
99
32
 
100
- span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CREATE_AGENT} {AGENT_NAME}'
33
+ span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CREATE_AGENT} {agent_name}"
101
34
 
102
35
  with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
103
- try:
104
- start_time = time.time()
105
- response = wrapped(*args, **kwargs)
106
- end_time = time.time()
107
-
108
- set_span_attributes(span, version, SemanticConvention.GEN_AI_OPERATION_TYPE_CREATE_AGENT,
109
- environment, application_name, server_address, server_port, REQUEST_MODEL)
110
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_DESCRIPTION, SYSTEM_MESSAGE)
111
- span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, REQUEST_MODEL)
112
- span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, end_time - start_time)
113
-
114
- span.set_status(Status(StatusCode.OK))
36
+ start_time = time.time()
37
+ response = wrapped(*args, **kwargs)
115
38
 
116
- return response
39
+ try:
40
+ process_agent_creation(
41
+ agent_name=agent_name,
42
+ llm_config=llm_config,
43
+ system_message=system_message,
44
+ pricing_info=pricing_info,
45
+ server_port=server_port,
46
+ server_address=server_address,
47
+ environment=environment,
48
+ application_name=application_name,
49
+ metrics=metrics,
50
+ start_time=start_time,
51
+ span=span,
52
+ capture_message_content=capture_message_content,
53
+ disable_metrics=disable_metrics,
54
+ version=version
55
+ )
117
56
 
118
57
  except Exception as e:
119
58
  handle_exception(span, e)
120
- logger.error('Error in trace creation: %s', e)
121
- return response
59
+
60
+ return response
122
61
 
123
62
  return wrapper
124
63
 
125
- def agent_run(version, environment, application_name,
126
- tracer, event_provider, pricing_info, capture_message_content, metrics, disable_metrics):
64
+ def agent_run(version, environment, application_name, tracer, pricing_info,
65
+ capture_message_content, metrics, disable_metrics):
127
66
  """
128
- Generates a telemetry wrapper for GenAI function call
67
+ Generates a telemetry wrapper for AG2 agent run execution.
129
68
  """
69
+
130
70
  def wrapper(wrapped, instance, args, kwargs):
131
- server_address, server_port = '127.0.0.1', 80
71
+ """
72
+ Wraps the AG2 agent run execution call.
73
+ """
132
74
 
133
- span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_EXECUTE_AGENT_TASK} {AGENT_NAME}'
75
+ server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 80)
134
76
 
135
- with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
136
- try:
137
- start_time = time.time()
138
- response = wrapped(*args, **kwargs)
139
- end_time = time.time()
77
+ # Extract agent name from instance
78
+ agent_name = getattr(instance, "name", "NOT_FOUND")
140
79
 
141
- input_tokens, output_tokens, cost = calculate_tokens_and_cost(response, REQUEST_MODEL, pricing_info)
142
- response_model = list(response.cost.get('usage_including_cached_inference', {}).keys())[1]
80
+ # Extract model from instance llm_config
81
+ request_model = "gpt-4o"
82
+ if hasattr(instance, "llm_config") and isinstance(instance.llm_config, dict):
83
+ request_model = instance.llm_config.get("model", "gpt-4o")
143
84
 
144
- set_span_attributes(span, version, SemanticConvention.GEN_AI_OPERATION_TYPE_EXECUTE_AGENT_TASK,
145
- environment, application_name, server_address, server_port, REQUEST_MODEL)
146
- span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, response_model)
147
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, input_tokens)
148
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens)
149
- span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, input_tokens + output_tokens)
150
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
151
- span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, end_time - start_time)
85
+ span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_EXECUTE_AGENT_TASK} {agent_name}"
152
86
 
153
- emit_events(response, event_provider, capture_message_content)
154
- span.set_status(Status(StatusCode.OK))
87
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
88
+ start_time = time.time()
89
+ response = wrapped(*args, **kwargs)
155
90
 
156
- return response
91
+ try:
92
+ response = process_agent_run(
93
+ response=response,
94
+ agent_name=agent_name,
95
+ request_model=request_model,
96
+ pricing_info=pricing_info,
97
+ server_port=server_port,
98
+ server_address=server_address,
99
+ environment=environment,
100
+ application_name=application_name,
101
+ metrics=metrics,
102
+ start_time=start_time,
103
+ span=span,
104
+ capture_message_content=capture_message_content,
105
+ disable_metrics=disable_metrics,
106
+ version=version
107
+ )
157
108
 
158
109
  except Exception as e:
159
110
  handle_exception(span, e)
160
- logger.error('Error in trace creation: %s', e)
161
- return response
111
+
112
+ return response
162
113
 
163
114
  return wrapper
@@ -0,0 +1,114 @@
1
+ """
2
+ Module for monitoring AG2 API calls (async version).
3
+ """
4
+
5
+ import time
6
+ from opentelemetry.trace import SpanKind
7
+ from openlit.__helpers import (
8
+ handle_exception,
9
+ set_server_address_and_port
10
+ )
11
+ from openlit.instrumentation.ag2.utils import (
12
+ process_agent_creation,
13
+ process_agent_run,
14
+ )
15
+ from openlit.semcov import SemanticConvention
16
+
17
+ def async_conversable_agent(version, environment, application_name, tracer, pricing_info,
18
+ capture_message_content, metrics, disable_metrics):
19
+ """
20
+ Generates a telemetry wrapper for AG2 async conversable agent creation.
21
+ """
22
+
23
+ async def wrapper(wrapped, instance, args, kwargs):
24
+ """
25
+ Wraps the AG2 async conversable agent creation call.
26
+ """
27
+
28
+ server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 80)
29
+ agent_name = kwargs.get("name", "NOT_FOUND")
30
+ llm_config = kwargs.get("llm_config", {})
31
+ system_message = kwargs.get("system_message", "")
32
+
33
+ span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CREATE_AGENT} {agent_name}"
34
+
35
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
36
+ start_time = time.time()
37
+ response = await wrapped(*args, **kwargs)
38
+
39
+ try:
40
+ process_agent_creation(
41
+ agent_name=agent_name,
42
+ llm_config=llm_config,
43
+ system_message=system_message,
44
+ pricing_info=pricing_info,
45
+ server_port=server_port,
46
+ server_address=server_address,
47
+ environment=environment,
48
+ application_name=application_name,
49
+ metrics=metrics,
50
+ start_time=start_time,
51
+ span=span,
52
+ capture_message_content=capture_message_content,
53
+ disable_metrics=disable_metrics,
54
+ version=version
55
+ )
56
+
57
+ except Exception as e:
58
+ handle_exception(span, e)
59
+
60
+ return response
61
+
62
+ return wrapper
63
+
64
+ def async_agent_run(version, environment, application_name, tracer, pricing_info,
65
+ capture_message_content, metrics, disable_metrics):
66
+ """
67
+ Generates a telemetry wrapper for AG2 async agent run execution.
68
+ """
69
+
70
+ async def wrapper(wrapped, instance, args, kwargs):
71
+ """
72
+ Wraps the AG2 async agent run execution call.
73
+ """
74
+
75
+ server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 80)
76
+
77
+ # Extract agent name from instance
78
+ agent_name = getattr(instance, "name", "NOT_FOUND")
79
+
80
+ # Extract model from instance llm_config
81
+ request_model = "gpt-4o"
82
+ if hasattr(instance, "llm_config") and isinstance(instance.llm_config, dict):
83
+ request_model = instance.llm_config.get("model", "gpt-4o")
84
+
85
+ span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_EXECUTE_AGENT_TASK} {agent_name}"
86
+
87
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
88
+ start_time = time.time()
89
+ response = await wrapped(*args, **kwargs)
90
+
91
+ try:
92
+ response = process_agent_run(
93
+ response=response,
94
+ agent_name=agent_name,
95
+ request_model=request_model,
96
+ pricing_info=pricing_info,
97
+ server_port=server_port,
98
+ server_address=server_address,
99
+ environment=environment,
100
+ application_name=application_name,
101
+ metrics=metrics,
102
+ start_time=start_time,
103
+ span=span,
104
+ capture_message_content=capture_message_content,
105
+ disable_metrics=disable_metrics,
106
+ version=version
107
+ )
108
+
109
+ except Exception as e:
110
+ handle_exception(span, e)
111
+
112
+ return response
113
+
114
+ return wrapper