openlit 1.34.26__py3-none-any.whl → 1.34.28__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 (37) hide show
  1. openlit/__helpers.py +38 -0
  2. openlit/__init__.py +22 -155
  3. openlit/_instrumentors.py +144 -0
  4. openlit/guard/all.py +3 -3
  5. openlit/instrumentation/astra/__init__.py +71 -159
  6. openlit/instrumentation/astra/astra.py +32 -22
  7. openlit/instrumentation/astra/async_astra.py +32 -22
  8. openlit/instrumentation/astra/utils.py +263 -88
  9. openlit/instrumentation/chroma/utils.py +2 -2
  10. openlit/instrumentation/controlflow/controlflow.py +2 -2
  11. openlit/instrumentation/embedchain/embedchain.py +4 -4
  12. openlit/instrumentation/groq/__init__.py +4 -4
  13. openlit/instrumentation/haystack/__init__.py +57 -28
  14. openlit/instrumentation/haystack/async_haystack.py +54 -0
  15. openlit/instrumentation/haystack/haystack.py +35 -65
  16. openlit/instrumentation/haystack/utils.py +377 -0
  17. openlit/instrumentation/julep/async_julep.py +2 -2
  18. openlit/instrumentation/julep/julep.py +2 -2
  19. openlit/instrumentation/langchain_community/utils.py +2 -2
  20. openlit/instrumentation/llamaindex/__init__.py +165 -37
  21. openlit/instrumentation/llamaindex/async_llamaindex.py +53 -0
  22. openlit/instrumentation/llamaindex/llamaindex.py +32 -64
  23. openlit/instrumentation/llamaindex/utils.py +412 -0
  24. openlit/instrumentation/mem0/mem0.py +2 -2
  25. openlit/instrumentation/milvus/__init__.py +30 -68
  26. openlit/instrumentation/milvus/milvus.py +34 -161
  27. openlit/instrumentation/milvus/utils.py +276 -0
  28. openlit/instrumentation/openai/__init__.py +24 -24
  29. openlit/instrumentation/openai/utils.py +10 -4
  30. openlit/instrumentation/pinecone/utils.py +2 -2
  31. openlit/instrumentation/qdrant/utils.py +2 -2
  32. openlit/instrumentation/together/__init__.py +8 -8
  33. openlit/semcov/__init__.py +79 -0
  34. {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/METADATA +1 -1
  35. {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/RECORD +37 -31
  36. {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/LICENSE +0 -0
  37. {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/WHEEL +0 -0
@@ -1,179 +1,52 @@
1
- # pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, possibly-used-before-assignment, too-many-branches
2
1
  """
3
- Module for monitoring Milvus.
2
+ Module for monitoring Milvus API calls.
4
3
  """
5
4
 
6
- import logging
7
- from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
5
+ import time
6
+ from opentelemetry.trace import SpanKind
7
+ from opentelemetry import context as context_api
9
8
  from openlit.__helpers import handle_exception
10
- from openlit.semcov import SemanticConvention
11
-
12
- # Initialize logger for logging potential issues and operations
13
- logger = logging.getLogger(__name__)
14
-
15
- def object_count(obj):
16
- """
17
- Counts Length of object if it exists, Else returns None
18
- """
19
- try:
20
- cnt = len(obj)
21
- # pylint: disable=bare-except
22
- except:
23
- cnt = 0
24
-
25
- return cnt
9
+ from openlit.instrumentation.milvus.utils import (
10
+ process_milvus_response,
11
+ DB_OPERATION_MAP,
12
+ set_server_address_and_port,
13
+ )
26
14
 
27
15
  def general_wrap(gen_ai_endpoint, version, environment, application_name,
28
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
16
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics):
29
17
  """
30
- Creates a wrapper around a function call to trace and log its execution metrics.
31
-
32
- This function wraps any given function to measure its execution time,
33
- log its operation, and trace its execution using OpenTelemetry.
34
-
35
- Parameters:
36
- - gen_ai_endpoint (str): A descriptor or name for the endpoint being traced.
37
- - version (str): The version of the Langchain application.
38
- - environment (str): The deployment environment (e.g., 'production', 'development').
39
- - application_name (str): Name of the Langchain application.
40
- - tracer (opentelemetry.trace.Tracer): The tracer object used for OpenTelemetry tracing.
41
- - pricing_info (dict): Information about the pricing for internal metrics (currently not used).
42
- - capture_message_content (bool): Flag indicating whether to trace the content of the response.
43
-
44
- Returns:
45
- - function: A higher-order function that takes a function 'wrapped' and returns
46
- a new function that wraps 'wrapped' with additional tracing and logging.
18
+ Generates a telemetry wrapper for Milvus function calls.
47
19
  """
48
-
49
20
  def wrapper(wrapped, instance, args, kwargs):
50
- """
51
- An inner wrapper function that executes the wrapped function, measures execution
52
- time, and records trace data using OpenTelemetry.
53
-
54
- Parameters:
55
- - wrapped (Callable): The original function that this wrapper will execute.
56
- - instance (object): The instance to which the wrapped function belongs. This
57
- is used for instance methods. For static and classmethods,
58
- this may be None.
59
- - args (tuple): Positional arguments passed to the wrapped function.
60
- - kwargs (dict): Keyword arguments passed to the wrapped function.
61
-
62
- Returns:
63
- - The result of the wrapped function call.
64
-
65
- The wrapper initiates a span with the provided tracer, sets various attributes
66
- on the span based on the function's execution and response, and ensures
67
- errors are handled and logged appropriately.
68
- """
69
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
21
+ # CRITICAL: Suppression check
22
+ if context_api.get_value(context_api._SUPPRESS_INSTRUMENTATION_KEY):
23
+ return wrapped(*args, **kwargs)
24
+
25
+ # Get server address and port using the standard helper
26
+ server_address, server_port = set_server_address_and_port(instance)
27
+
28
+ db_operation = DB_OPERATION_MAP.get(gen_ai_endpoint, "unknown")
29
+ if db_operation == "create_collection":
30
+ collection_name = kwargs.get("collection_name") or (args[0] if args else "unknown")
31
+ else:
32
+ collection_name = kwargs.get("collection_name", "unknown")
33
+ span_name = f"{db_operation} {collection_name}"
34
+
35
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
36
+ start_time = time.time()
70
37
  response = wrapped(*args, **kwargs)
71
38
 
72
39
  try:
73
- span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
74
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
75
- gen_ai_endpoint)
76
- span.set_attribute(DEPLOYMENT_ENVIRONMENT,
77
- environment)
78
- span.set_attribute(SERVICE_NAME,
79
- application_name)
80
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
81
- SemanticConvention.GEN_AI_OPERATION_TYPE_VECTORDB)
82
- span.set_attribute(SemanticConvention.DB_SYSTEM_NAME,
83
- SemanticConvention.DB_SYSTEM_MILVUS)
84
-
85
- if gen_ai_endpoint == "milvus.create_collection":
86
- db_operation = SemanticConvention.DB_OPERATION_CREATE_COLLECTION
87
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
88
- SemanticConvention.DB_OPERATION_CREATE_COLLECTION)
89
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
90
- kwargs.get("collection_name", ""))
91
- span.set_attribute(SemanticConvention.DB_COLLECTION_DIMENSION,
92
- kwargs.get("dimension", ""))
93
-
94
- elif gen_ai_endpoint == "milvus.drop_collection":
95
- db_operation = SemanticConvention.DB_OPERATION_DELETE_COLLECTION
96
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
97
- SemanticConvention.DB_OPERATION_DELETE_COLLECTION)
98
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
99
- kwargs.get("collection_name", ""))
100
-
101
- elif gen_ai_endpoint == "milvus.insert":
102
- db_operation = SemanticConvention.DB_OPERATION_ADD
103
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
104
- SemanticConvention.DB_OPERATION_ADD)
105
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
106
- kwargs.get("collection_name", ""))
107
- span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
108
- object_count(kwargs.get("data")))
109
- span.set_attribute(SemanticConvention.DB_OPERATION_COST,
110
- response["cost"])
111
-
112
- elif gen_ai_endpoint == "milvus.search":
113
- db_operation = SemanticConvention.DB_OPERATION_QUERY
114
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
115
- SemanticConvention.DB_OPERATION_QUERY)
116
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
117
- kwargs.get("collection_name", ""))
118
- span.set_attribute(SemanticConvention.DB_STATEMENT,
119
- str(kwargs.get("data")))
120
-
121
- elif gen_ai_endpoint in ["milvus.query", "milvus.get"]:
122
- db_operation = SemanticConvention.DB_OPERATION_QUERY
123
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
124
- SemanticConvention.DB_OPERATION_QUERY)
125
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
126
- kwargs.get("collection_name", ""))
127
- span.set_attribute(SemanticConvention.DB_STATEMENT,
128
- str(kwargs.get("output_fields")))
129
-
130
- elif gen_ai_endpoint == "milvus.upsert":
131
- db_operation = SemanticConvention.DB_OPERATION_ADD
132
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
133
- SemanticConvention.DB_OPERATION_UPSERT)
134
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
135
- kwargs.get("collection_name", ""))
136
- span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
137
- object_count(kwargs.get("data")))
138
- span.set_attribute(SemanticConvention.DB_OPERATION_COST,
139
- response["cost"])
140
-
141
- elif gen_ai_endpoint == "milvus.delete":
142
- db_operation = SemanticConvention.DB_OPERATION_DELETE
143
- span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
144
- SemanticConvention.DB_OPERATION_DELETE)
145
- span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
146
- kwargs.get("collection_name", ""))
147
- span.set_attribute(SemanticConvention.DB_FILTER,
148
- str(kwargs.get("filter", "")))
149
-
150
- span.set_status(Status(StatusCode.OK))
151
-
152
- if disable_metrics is False:
153
- attributes = {
154
- TELEMETRY_SDK_NAME:
155
- "openlit",
156
- SERVICE_NAME:
157
- application_name,
158
- SemanticConvention.DB_SYSTEM_NAME:
159
- SemanticConvention.DB_SYSTEM_MILVUS,
160
- DEPLOYMENT_ENVIRONMENT:
161
- environment,
162
- SemanticConvention.GEN_AI_OPERATION:
163
- SemanticConvention.GEN_AI_OPERATION_TYPE_VECTORDB,
164
- SemanticConvention.DB_OPERATION_NAME:
165
- db_operation
166
- }
167
-
168
- metrics["db_requests"].add(1, attributes)
169
-
170
- return response
40
+ # Process response and generate telemetry
41
+ response = process_milvus_response(
42
+ response, db_operation, server_address, server_port,
43
+ environment, application_name, metrics, start_time, span,
44
+ capture_message_content, disable_metrics, version, instance, args, **kwargs
45
+ )
171
46
 
172
47
  except Exception as e:
173
48
  handle_exception(span, e)
174
- logger.error("Error in trace creation: %s", e)
175
49
 
176
- # Return original response
177
- return response
50
+ return response
178
51
 
179
52
  return wrapper
@@ -0,0 +1,276 @@
1
+ """
2
+ Utility functions for Milvus instrumentation.
3
+ """
4
+
5
+ import time
6
+ from urllib.parse import urlparse
7
+ from opentelemetry.trace import Status, StatusCode
8
+ from openlit.__helpers import (
9
+ common_db_span_attributes,
10
+ record_db_metrics,
11
+ )
12
+ from openlit.semcov import SemanticConvention
13
+
14
+ # Operation mapping for simple span naming
15
+ DB_OPERATION_MAP = {
16
+ "milvus.create_collection": SemanticConvention.DB_OPERATION_CREATE_COLLECTION,
17
+ "milvus.drop_collection": SemanticConvention.DB_OPERATION_DELETE_COLLECTION,
18
+ "milvus.insert": SemanticConvention.DB_OPERATION_INSERT,
19
+ "milvus.upsert": SemanticConvention.DB_OPERATION_UPSERT,
20
+ "milvus.search": SemanticConvention.DB_OPERATION_SEARCH,
21
+ "milvus.query": SemanticConvention.DB_OPERATION_QUERY,
22
+ "milvus.get": SemanticConvention.DB_OPERATION_GET,
23
+ "milvus.delete": SemanticConvention.DB_OPERATION_DELETE,
24
+ }
25
+
26
+ def object_count(obj):
27
+ """
28
+ Counts length of object if it exists, else returns 0.
29
+ """
30
+ return len(obj) if obj else 0
31
+
32
+ def set_server_address_and_port(instance):
33
+ """
34
+ Extracts server address and port from Milvus client instance.
35
+
36
+ Args:
37
+ instance: Milvus client instance
38
+
39
+ Returns:
40
+ tuple: (server_address, server_port)
41
+ """
42
+ server_address = "localhost"
43
+ server_port = 19530 # Default Milvus port
44
+
45
+ # Try getting uri from multiple potential attributes
46
+ client_config = getattr(instance, "_client_config", None)
47
+ if client_config:
48
+ uri = getattr(client_config, "uri", None)
49
+ if uri and isinstance(uri, str):
50
+ if uri.startswith(("http://", "https://")):
51
+ try:
52
+ parsed = urlparse(uri)
53
+ server_address = parsed.hostname or server_address
54
+ server_port = parsed.port or server_port
55
+ except Exception:
56
+ pass
57
+ else:
58
+ # Handle cases like "localhost:19530" or just "localhost"
59
+ if ":" in uri:
60
+ parts = uri.split(":")
61
+ server_address = parts[0]
62
+ try:
63
+ server_port = int(parts[1])
64
+ except (ValueError, IndexError):
65
+ pass
66
+ else:
67
+ server_address = uri
68
+
69
+ return server_address, server_port
70
+
71
+ def common_milvus_logic(scope, environment, application_name,
72
+ metrics, capture_message_content, disable_metrics, version,
73
+ instance=None, endpoint=None):
74
+ """
75
+ Process Milvus database request and generate telemetry.
76
+
77
+ Args:
78
+ scope: Scope object containing span, response, and operation details
79
+ environment: Deployment environment
80
+ application_name: Name of the application
81
+ metrics: Metrics dictionary for recording telemetry
82
+ capture_message_content: Flag to capture message content
83
+ disable_metrics: Flag to disable metrics collection
84
+ version: Version of the Milvus client
85
+ instance: Milvus client instance
86
+ endpoint: Operation endpoint for differentiation
87
+ """
88
+ scope._end_time = time.time()
89
+
90
+ # Set common database span attributes using helper
91
+ common_db_span_attributes(scope, SemanticConvention.DB_SYSTEM_MILVUS,
92
+ scope._server_address, scope._server_port, environment, application_name, version)
93
+
94
+ # Set DB operation specific attributes
95
+ scope._span.set_attribute(SemanticConvention.DB_OPERATION_NAME, scope._db_operation)
96
+ scope._span.set_attribute(SemanticConvention.DB_CLIENT_OPERATION_DURATION,
97
+ scope._end_time - scope._start_time)
98
+
99
+ if scope._db_operation == SemanticConvention.DB_OPERATION_CREATE_COLLECTION:
100
+ collection_name = scope._kwargs.get("collection_name", "unknown")
101
+
102
+ # Standard database attributes
103
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
104
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_DIMENSION,
105
+ scope._kwargs.get("dimension", -1))
106
+
107
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
108
+ f"{scope._db_operation} {collection_name} "
109
+ f"dimension={scope._kwargs.get('dimension', 'None')}")
110
+
111
+ elif scope._db_operation == SemanticConvention.DB_OPERATION_DELETE_COLLECTION:
112
+ collection_name = scope._kwargs.get("collection_name", "unknown")
113
+
114
+ # Standard database attributes
115
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
116
+
117
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
118
+ f"{scope._db_operation} {collection_name}")
119
+
120
+ elif scope._db_operation == SemanticConvention.DB_OPERATION_INSERT:
121
+ collection_name = scope._kwargs.get("collection_name", "unknown")
122
+ data = scope._kwargs.get("data", [])
123
+
124
+ # Standard database attributes
125
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
126
+ scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(data))
127
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(data))
128
+
129
+ # Response metrics
130
+ if scope._response and scope._response.get("insert_count"):
131
+ scope._span.set_attribute(SemanticConvention.DB_RESPONSE_RETURNED_ROWS,
132
+ scope._response["insert_count"])
133
+
134
+ if scope._response and scope._response.get("cost"):
135
+ scope._span.set_attribute(SemanticConvention.DB_OPERATION_COST,
136
+ scope._response["cost"])
137
+
138
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
139
+ f"{scope._db_operation} {collection_name} "
140
+ f"data_count={object_count(data)}")
141
+
142
+ elif scope._db_operation == SemanticConvention.DB_OPERATION_UPSERT:
143
+ collection_name = scope._kwargs.get("collection_name", "unknown")
144
+ data = scope._kwargs.get("data", [])
145
+
146
+ # Standard database attributes
147
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
148
+ scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(data))
149
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(data))
150
+
151
+ # Response metrics
152
+ if scope._response and scope._response.get("upsert_count"):
153
+ scope._span.set_attribute(SemanticConvention.DB_RESPONSE_RETURNED_ROWS,
154
+ scope._response["upsert_count"])
155
+
156
+ if scope._response and scope._response.get("cost"):
157
+ scope._span.set_attribute(SemanticConvention.DB_OPERATION_COST,
158
+ scope._response["cost"])
159
+
160
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
161
+ f"{scope._db_operation} {collection_name} "
162
+ f"data_count={object_count(data)}")
163
+
164
+ elif scope._db_operation == SemanticConvention.DB_OPERATION_SEARCH:
165
+ collection_name = scope._kwargs.get("collection_name", "unknown")
166
+ data = scope._kwargs.get("data", [])
167
+
168
+ # Standard database attributes
169
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
170
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(data))
171
+ scope._span.set_attribute(SemanticConvention.DB_VECTOR_QUERY_TOP_K,
172
+ scope._kwargs.get("limit", -1))
173
+
174
+ # Search specific attributes
175
+ scope._span.set_attribute(SemanticConvention.DB_FILTER,
176
+ str(scope._kwargs.get("filter", "")))
177
+
178
+ # Response metrics
179
+ if scope._response and isinstance(scope._response, list):
180
+ scope._span.set_attribute(SemanticConvention.DB_RESPONSE_RETURNED_ROWS,
181
+ len(scope._response))
182
+
183
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
184
+ f"{scope._db_operation} {collection_name} "
185
+ f"data={str(data)[:100]}... "
186
+ f"limit={scope._kwargs.get('limit', 'None')}")
187
+
188
+ elif scope._db_operation in [SemanticConvention.DB_OPERATION_QUERY, SemanticConvention.DB_OPERATION_GET]:
189
+ collection_name = scope._kwargs.get("collection_name", "unknown")
190
+ output_fields = scope._kwargs.get("output_fields", [])
191
+
192
+ # Standard database attributes
193
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
194
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(output_fields))
195
+
196
+ # Query specific attributes
197
+ scope._span.set_attribute(SemanticConvention.DB_FILTER,
198
+ str(scope._kwargs.get("filter", "")))
199
+
200
+ # Response metrics
201
+ if scope._response and isinstance(scope._response, list):
202
+ scope._span.set_attribute(SemanticConvention.DB_RESPONSE_RETURNED_ROWS,
203
+ len(scope._response))
204
+
205
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
206
+ f"{scope._db_operation} {collection_name} "
207
+ f"output_fields={output_fields} "
208
+ f"filter={scope._kwargs.get('filter', 'None')}")
209
+
210
+ elif scope._db_operation == SemanticConvention.DB_OPERATION_DELETE:
211
+ collection_name = scope._kwargs.get("collection_name", "unknown")
212
+
213
+ # Standard database attributes
214
+ scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
215
+ scope._span.set_attribute(SemanticConvention.DB_FILTER,
216
+ str(scope._kwargs.get("filter", "")))
217
+
218
+ # Response metrics
219
+ if scope._response and scope._response.get("delete_count"):
220
+ scope._span.set_attribute(SemanticConvention.DB_RESPONSE_RETURNED_ROWS,
221
+ scope._response["delete_count"])
222
+
223
+ scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
224
+ f"{scope._db_operation} {collection_name} "
225
+ f"filter={scope._kwargs.get('filter', 'None')}")
226
+
227
+ scope._span.set_status(Status(StatusCode.OK))
228
+
229
+ # Record metrics using helper
230
+ if not disable_metrics:
231
+ record_db_metrics(metrics, SemanticConvention.DB_SYSTEM_MILVUS,
232
+ scope._server_address, scope._server_port, environment, application_name,
233
+ scope._start_time, scope._end_time)
234
+
235
+ def process_milvus_response(response, db_operation, server_address, server_port,
236
+ environment, application_name, metrics, start_time, span,
237
+ capture_message_content, disable_metrics, version, instance, args, **kwargs):
238
+ """
239
+ Process Milvus response and generate telemetry.
240
+
241
+ Args:
242
+ response: Response from Milvus operation
243
+ db_operation: Database operation type
244
+ server_address: Server address
245
+ server_port: Server port
246
+ environment: Deployment environment
247
+ application_name: Application name
248
+ metrics: Metrics dictionary
249
+ start_time: Start time of the operation
250
+ span: OpenTelemetry span
251
+ capture_message_content: Flag to capture message content
252
+ disable_metrics: Flag to disable metrics
253
+ version: Milvus client version
254
+ instance: Milvus client instance
255
+ args: Positional arguments
256
+ **kwargs: Keyword arguments
257
+
258
+ Returns:
259
+ Original response
260
+ """
261
+
262
+ # Create a scope object to hold all the context
263
+ scope = type("GenericScope", (), {})()
264
+ scope._response = response
265
+ scope._db_operation = db_operation
266
+ scope._server_address = server_address
267
+ scope._server_port = server_port
268
+ scope._start_time = start_time
269
+ scope._span = span
270
+ scope._kwargs = kwargs
271
+
272
+ # Process the response using common logic
273
+ common_milvus_logic(scope, environment, application_name,
274
+ metrics, capture_message_content, disable_metrics, version, instance)
275
+
276
+ return response
@@ -35,15 +35,15 @@ class OpenAIInstrumentor(BaseInstrumentor):
35
35
 
36
36
  # chat completions
37
37
  wrap_function_wrapper(
38
- "openai.resources.chat.completions",
39
- "Completions.create",
38
+ "openai.resources.chat.completions",
39
+ "Completions.create",
40
40
  chat_completions(version, environment, application_name,
41
41
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
42
42
  )
43
43
 
44
44
  wrap_function_wrapper(
45
- "openai.resources.chat.completions",
46
- "AsyncCompletions.create",
45
+ "openai.resources.chat.completions",
46
+ "AsyncCompletions.create",
47
47
  async_chat_completions(version, environment, application_name,
48
48
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
49
49
  )
@@ -65,75 +65,75 @@ class OpenAIInstrumentor(BaseInstrumentor):
65
65
 
66
66
  # responses
67
67
  wrap_function_wrapper(
68
- "openai.resources.responses.responses",
69
- "Responses.create",
68
+ "openai.resources.responses.responses",
69
+ "Responses.create",
70
70
  responses(version, environment, application_name,
71
71
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
72
72
  )
73
73
 
74
74
  wrap_function_wrapper(
75
- "openai.resources.responses.responses",
76
- "AsyncResponses.create",
75
+ "openai.resources.responses.responses",
76
+ "AsyncResponses.create",
77
77
  async_responses(version, environment, application_name,
78
78
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
79
79
  )
80
80
 
81
81
  # embeddings
82
82
  wrap_function_wrapper(
83
- "openai.resources.embeddings",
84
- "Embeddings.create",
83
+ "openai.resources.embeddings",
84
+ "Embeddings.create",
85
85
  embedding(version, environment, application_name,
86
86
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
87
87
  )
88
88
 
89
89
  wrap_function_wrapper(
90
- "openai.resources.embeddings",
91
- "AsyncEmbeddings.create",
90
+ "openai.resources.embeddings",
91
+ "AsyncEmbeddings.create",
92
92
  async_embedding(version, environment, application_name,
93
93
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
94
94
  )
95
95
 
96
96
  # image generation
97
97
  wrap_function_wrapper(
98
- "openai.resources.images",
99
- "Images.generate",
98
+ "openai.resources.images",
99
+ "Images.generate",
100
100
  image_generate(version, environment, application_name,
101
101
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
102
102
  )
103
103
 
104
104
  wrap_function_wrapper(
105
- "openai.resources.images",
106
- "AsyncImages.generate",
105
+ "openai.resources.images",
106
+ "AsyncImages.generate",
107
107
  async_image_generate(version, environment, application_name,
108
108
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
109
109
  )
110
110
 
111
111
  # image variations
112
112
  wrap_function_wrapper(
113
- "openai.resources.images",
114
- "Images.create_variation",
113
+ "openai.resources.images",
114
+ "Images.create_variation",
115
115
  image_variatons(version, environment, application_name,
116
116
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
117
117
  )
118
118
 
119
119
  wrap_function_wrapper(
120
- "openai.resources.images",
121
- "AsyncImages.create_variation",
120
+ "openai.resources.images",
121
+ "AsyncImages.create_variation",
122
122
  async_image_variations(version, environment, application_name,
123
123
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
124
124
  )
125
125
 
126
126
  # audio generation
127
127
  wrap_function_wrapper(
128
- "openai.resources.audio.speech",
129
- "Speech.create",
128
+ "openai.resources.audio.speech",
129
+ "Speech.create",
130
130
  audio_create(version, environment, application_name,
131
131
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
132
132
  )
133
133
 
134
134
  wrap_function_wrapper(
135
- "openai.resources.audio.speech",
136
- "AsyncSpeech.create",
135
+ "openai.resources.audio.speech",
136
+ "AsyncSpeech.create",
137
137
  async_audio_create(version, environment, application_name,
138
138
  tracer, pricing_info, capture_message_content, metrics, disable_metrics),
139
139
  )
@@ -37,9 +37,15 @@ def format_content(messages):
37
37
 
38
38
  # Handle list of messages
39
39
  formatted_messages = []
40
+
40
41
  for message in messages:
41
- role = message.get("role", "user")
42
- content = message.get("content", "")
42
+ try:
43
+ role = message.get("role", "user") or message.role
44
+ content = message.get("content", "") or message.content
45
+
46
+ except:
47
+ role = "user"
48
+ content = str(messages)
43
49
 
44
50
  if isinstance(content, list):
45
51
  content_str_list = []
@@ -442,9 +448,9 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
442
448
  scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
443
449
 
444
450
  # OpenAI-specific attributes
445
- if hasattr(scope, "_system_fingerprint"):
451
+ if hasattr(scope, "_system_fingerprint") and scope._system_fingerprint:
446
452
  scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_SYSTEM_FINGERPRINT, scope._system_fingerprint)
447
- if hasattr(scope, "_service_tier"):
453
+ if hasattr(scope, "_service_tier") and scope._service_tier:
448
454
  scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SERVICE_TIER, scope._service_tier)
449
455
 
450
456
  # Span Attributes for Tools - optimized
@@ -33,10 +33,10 @@ def object_count(obj):
33
33
  def set_server_address_and_port(instance):
34
34
  """
35
35
  Extracts server address and port from Pinecone client instance.
36
-
36
+
37
37
  Args:
38
38
  instance: Pinecone client instance
39
-
39
+
40
40
  Returns:
41
41
  tuple: (server_address, server_port)
42
42
  """
@@ -47,10 +47,10 @@ def object_count(obj):
47
47
  def set_server_address_and_port(instance):
48
48
  """
49
49
  Extracts server address and port from Qdrant client instance.
50
-
50
+
51
51
  Args:
52
52
  instance: Qdrant client instance
53
-
53
+
54
54
  Returns:
55
55
  tuple: (server_address, server_port)
56
56
  """