openlit 1.34.25__py3-none-any.whl → 1.34.26__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/instrumentation/chroma/__init__.py +1 -1
- openlit/instrumentation/chroma/chroma.py +6 -8
- openlit/instrumentation/chroma/utils.py +48 -3
- openlit/instrumentation/pinecone/__init__.py +46 -142
- openlit/instrumentation/pinecone/async_pinecone.py +6 -8
- openlit/instrumentation/pinecone/pinecone.py +6 -8
- openlit/instrumentation/pinecone/utils.py +41 -1
- openlit/instrumentation/qdrant/__init__.py +52 -267
- openlit/instrumentation/qdrant/async_qdrant.py +32 -244
- openlit/instrumentation/qdrant/qdrant.py +32 -251
- openlit/instrumentation/qdrant/utils.py +328 -0
- {openlit-1.34.25.dist-info → openlit-1.34.26.dist-info}/METADATA +1 -1
- {openlit-1.34.25.dist-info → openlit-1.34.26.dist-info}/RECORD +15 -14
- {openlit-1.34.25.dist-info → openlit-1.34.26.dist-info}/LICENSE +0 -0
- {openlit-1.34.25.dist-info → openlit-1.34.26.dist-info}/WHEEL +0 -0
@@ -1,274 +1,55 @@
|
|
1
1
|
# pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, possibly-used-before-assignment, too-many-branches
|
2
2
|
"""
|
3
|
-
Module for monitoring Qdrant.
|
3
|
+
Module for monitoring Qdrant operations.
|
4
4
|
"""
|
5
5
|
|
6
|
-
import
|
7
|
-
from opentelemetry.trace import SpanKind
|
8
|
-
from opentelemetry
|
6
|
+
import time
|
7
|
+
from opentelemetry.trace import SpanKind
|
8
|
+
from opentelemetry import context as context_api
|
9
9
|
from openlit.__helpers import handle_exception
|
10
|
-
from openlit.
|
10
|
+
from openlit.instrumentation.qdrant.utils import DB_OPERATION_MAP, process_qdrant_response, set_server_address_and_port
|
11
11
|
|
12
|
-
|
13
|
-
|
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
|
26
|
-
|
27
|
-
def general_wrap(gen_ai_endpoint, version, environment, application_name,
|
28
|
-
tracer, pricing_info, capture_message_content, metrics, disable_metrics):
|
12
|
+
def general_wrap(gen_ai_endpoint, version, environment, application_name, tracer,
|
13
|
+
pricing_info, capture_message_content, metrics, disable_metrics):
|
29
14
|
"""
|
30
|
-
|
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.
|
15
|
+
Generates a telemetry wrapper for Pinecone function calls.
|
47
16
|
"""
|
48
17
|
|
49
18
|
def wrapper(wrapped, instance, args, kwargs):
|
50
19
|
"""
|
51
|
-
|
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.
|
20
|
+
Wraps the Qdrant operation with tracing and logging.
|
68
21
|
"""
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
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_QDRANT)
|
84
|
-
|
85
|
-
if gen_ai_endpoint == "qdrant.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
|
-
|
92
|
-
elif gen_ai_endpoint == "qdrant.upload_collection":
|
93
|
-
db_operation = SemanticConvention.DB_OPERATION_CREATE_COLLECTION
|
94
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
95
|
-
SemanticConvention.DB_OPERATION_CREATE_COLLECTION)
|
96
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
97
|
-
kwargs.get("collection_name", ""))
|
98
|
-
|
99
|
-
elif gen_ai_endpoint == "qdrant.delete_collection":
|
100
|
-
db_operation = SemanticConvention.DB_OPERATION_DELETE_COLLECTION
|
101
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
102
|
-
SemanticConvention.DB_OPERATION_DELETE_COLLECTION)
|
103
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
104
|
-
kwargs.get("collection_name", ""))
|
22
|
+
# CRITICAL: Suppression check
|
23
|
+
if context_api.get_value(context_api._SUPPRESS_INSTRUMENTATION_KEY):
|
24
|
+
return wrapped(*args, **kwargs)
|
105
25
|
|
106
|
-
|
107
|
-
|
108
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
109
|
-
SemanticConvention.DB_OPERATION_UPDATE_COLLECTION)
|
110
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
111
|
-
kwargs.get("collection_name", ""))
|
26
|
+
# Extract operation from endpoint
|
27
|
+
db_operation = DB_OPERATION_MAP.get(gen_ai_endpoint, "unknown")
|
112
28
|
|
113
|
-
|
114
|
-
|
115
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
116
|
-
SemanticConvention.DB_OPERATION_ADD)
|
117
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
118
|
-
kwargs.get("collection_name", ""))
|
119
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
120
|
-
response.status)
|
121
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
122
|
-
object_count(kwargs.get("points", [])))
|
123
|
-
span.set_attribute(SemanticConvention.DB_PAYLOAD_COUNT,
|
124
|
-
object_count(kwargs.get("payload", [])))
|
29
|
+
# Server address calculation
|
30
|
+
server_address, server_port = set_server_address_and_port(instance)
|
125
31
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
SemanticConvention.DB_OPERATION_QUERY)
|
130
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
131
|
-
kwargs.get("collection_name", ""))
|
132
|
-
span.set_attribute(SemanticConvention.DB_STATEMENT,
|
133
|
-
str(kwargs.get("ids", "")))
|
32
|
+
# Span naming: use operation + collection
|
33
|
+
collection_name = kwargs.get("collection_name", "unknown")
|
34
|
+
span_name = f"{db_operation} {collection_name}"
|
134
35
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
140
|
-
kwargs.get("collection_name", ""))
|
141
|
-
span.set_attribute(SemanticConvention.DB_STATEMENT,
|
142
|
-
str(kwargs.get("scroll_filter", "")))
|
143
|
-
|
144
|
-
elif gen_ai_endpoint in ["qdrant.search", "qdrant.search_groups"]:
|
145
|
-
db_operation = SemanticConvention.DB_OPERATION_QUERY
|
146
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
147
|
-
SemanticConvention.DB_OPERATION_QUERY)
|
148
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
149
|
-
kwargs.get("collection_name", ""))
|
150
|
-
span.set_attribute(SemanticConvention.DB_STATEMENT,
|
151
|
-
str(kwargs.get("query_vector", "")))
|
152
|
-
|
153
|
-
elif gen_ai_endpoint == "qdrant.recommend":
|
154
|
-
db_operation = SemanticConvention.DB_OPERATION_QUERY
|
155
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
156
|
-
SemanticConvention.DB_OPERATION_QUERY)
|
157
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
158
|
-
kwargs.get("collection_name", ""))
|
159
|
-
span.set_attribute(SemanticConvention.DB_STATEMENT,
|
160
|
-
"positive:" + str(kwargs.get("positive", "")) +
|
161
|
-
" negative:" + str(kwargs.get("negative", "")))
|
162
|
-
|
163
|
-
elif gen_ai_endpoint == "qdrant.upload_points":
|
164
|
-
db_operation = SemanticConvention.DB_OPERATION_ADD
|
165
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
166
|
-
SemanticConvention.DB_OPERATION_ADD)
|
167
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
168
|
-
kwargs.get("collection_name", ""))
|
169
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
170
|
-
object_count(kwargs.get("points")))
|
171
|
-
|
172
|
-
elif gen_ai_endpoint == "qdrant.update_vectors":
|
173
|
-
db_operation = SemanticConvention.DB_OPERATION_UPDATE
|
174
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
175
|
-
SemanticConvention.DB_OPERATION_UPDATE)
|
176
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
177
|
-
kwargs.get("collection_name", ""))
|
178
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
179
|
-
response.status)
|
180
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
181
|
-
object_count(kwargs.get("points")))
|
182
|
-
|
183
|
-
elif gen_ai_endpoint == "qdrant.overwrite_payload":
|
184
|
-
db_operation = SemanticConvention.DB_OPERATION_UPDATE
|
185
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
186
|
-
SemanticConvention.DB_OPERATION_UPDATE)
|
187
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
188
|
-
kwargs.get("collection_name", ""))
|
189
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
190
|
-
response.status)
|
191
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
192
|
-
object_count(kwargs.get("points")))
|
193
|
-
span.set_attribute(SemanticConvention.DB_PAYLOAD_COUNT,
|
194
|
-
object_count(kwargs.get("payload")))
|
195
|
-
|
196
|
-
elif gen_ai_endpoint == "qdrant.upsert":
|
197
|
-
db_operation = SemanticConvention.DB_OPERATION_UPSERT
|
198
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
199
|
-
kwargs.get("collection_name", ""))
|
200
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
201
|
-
SemanticConvention.DB_OPERATION_UPSERT)
|
202
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
203
|
-
response.status)
|
204
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
205
|
-
object_count(kwargs.get("points")))
|
206
|
-
|
207
|
-
elif gen_ai_endpoint in ["qdrant.delete_payload", "qdrant.delete_vectors"]:
|
208
|
-
db_operation = SemanticConvention.DB_OPERATION_DELETE
|
209
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
210
|
-
SemanticConvention.DB_OPERATION_DELETE)
|
211
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
212
|
-
kwargs.get("collection_name", ""))
|
213
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
214
|
-
response.status)
|
215
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
216
|
-
object_count(kwargs.get("points")))
|
217
|
-
|
218
|
-
elif gen_ai_endpoint in ["qdrant.clear_payload", "qdrant.delete"]:
|
219
|
-
db_operation = SemanticConvention.DB_OPERATION_DELETE
|
220
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
221
|
-
SemanticConvention.DB_OPERATION_DELETE)
|
222
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
223
|
-
kwargs.get("collection_name", ""))
|
224
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
225
|
-
response.status)
|
226
|
-
span.set_attribute(SemanticConvention.DB_VECTOR_COUNT,
|
227
|
-
object_count(kwargs.get("points_selector")))
|
228
|
-
|
229
|
-
elif gen_ai_endpoint == "qdrant.create_payload_index":
|
230
|
-
db_operation = SemanticConvention.DB_OPERATION_CREATE_INDEX
|
231
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
232
|
-
SemanticConvention.DB_OPERATION_CREATE_INDEX)
|
233
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
234
|
-
kwargs.get("collection_name", ""))
|
235
|
-
|
236
|
-
elif gen_ai_endpoint == "qdrant.query_points":
|
237
|
-
db_operation = SemanticConvention.DB_OPERATION_QUERY
|
238
|
-
span.set_attribute(SemanticConvention.DB_OPERATION_NAME,
|
239
|
-
SemanticConvention.DB_OPERATION_QUERY)
|
240
|
-
span.set_attribute(SemanticConvention.DB_COLLECTION_NAME,
|
241
|
-
kwargs.get("collection_name", ""))
|
242
|
-
span.set_attribute(SemanticConvention.DB_STATEMENT,
|
243
|
-
str(kwargs.get("query", "")))
|
244
|
-
|
245
|
-
span.set_status(Status(StatusCode.OK))
|
246
|
-
|
247
|
-
if disable_metrics is False:
|
248
|
-
attributes = {
|
249
|
-
TELEMETRY_SDK_NAME:
|
250
|
-
"openlit",
|
251
|
-
SERVICE_NAME:
|
252
|
-
application_name,
|
253
|
-
SemanticConvention.DB_SYSTEM_NAME:
|
254
|
-
SemanticConvention.DB_SYSTEM_QDRANT,
|
255
|
-
DEPLOYMENT_ENVIRONMENT:
|
256
|
-
environment,
|
257
|
-
SemanticConvention.GEN_AI_OPERATION:
|
258
|
-
SemanticConvention.GEN_AI_OPERATION_TYPE_VECTORDB,
|
259
|
-
SemanticConvention.DB_OPERATION_NAME:
|
260
|
-
db_operation
|
261
|
-
}
|
262
|
-
|
263
|
-
metrics["db_requests"].add(1, attributes)
|
36
|
+
# CRITICAL: Use tracer.start_as_current_span() for proper context
|
37
|
+
with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
|
38
|
+
start_time = time.time()
|
39
|
+
response = wrapped(*args, **kwargs)
|
264
40
|
|
265
|
-
|
41
|
+
try:
|
42
|
+
# Process response with endpoint information
|
43
|
+
response = process_qdrant_response(
|
44
|
+
response, db_operation, server_address, server_port,
|
45
|
+
environment, application_name, metrics, start_time, span,
|
46
|
+
capture_message_content, disable_metrics, version,
|
47
|
+
instance=instance, args=args, endpoint=gen_ai_endpoint, **kwargs
|
48
|
+
)
|
266
49
|
|
267
50
|
except Exception as e:
|
268
51
|
handle_exception(span, e)
|
269
|
-
logger.error("Error in trace creation: %s", e)
|
270
52
|
|
271
|
-
|
272
|
-
return response
|
53
|
+
return response
|
273
54
|
|
274
55
|
return wrapper
|
@@ -0,0 +1,328 @@
|
|
1
|
+
"""
|
2
|
+
Utilities for Qdrant 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 Qdrant endpoints
|
15
|
+
DB_OPERATION_MAP = {
|
16
|
+
"qdrant.create_collection": SemanticConvention.DB_OPERATION_CREATE_COLLECTION,
|
17
|
+
"qdrant.upload_collection": SemanticConvention.DB_OPERATION_CREATE_COLLECTION,
|
18
|
+
"qdrant.delete_collection": SemanticConvention.DB_OPERATION_DELETE_COLLECTION,
|
19
|
+
"qdrant.update_collection": SemanticConvention.DB_OPERATION_UPDATE_COLLECTION,
|
20
|
+
"qdrant.upsert": SemanticConvention.DB_OPERATION_UPSERT,
|
21
|
+
"qdrant.upload_points": SemanticConvention.DB_OPERATION_INSERT,
|
22
|
+
"qdrant.set_payload": SemanticConvention.DB_OPERATION_INSERT,
|
23
|
+
"qdrant.overwrite_payload": SemanticConvention.DB_OPERATION_UPDATE,
|
24
|
+
"qdrant.update_vectors": SemanticConvention.DB_OPERATION_UPDATE,
|
25
|
+
"qdrant.delete": SemanticConvention.DB_OPERATION_DELETE,
|
26
|
+
"qdrant.delete_vectors": SemanticConvention.DB_OPERATION_DELETE,
|
27
|
+
"qdrant.delete_payload": SemanticConvention.DB_OPERATION_DELETE,
|
28
|
+
"qdrant.clear_payload": SemanticConvention.DB_OPERATION_DELETE,
|
29
|
+
"qdrant.retrieve": SemanticConvention.DB_OPERATION_GET,
|
30
|
+
"qdrant.scroll": SemanticConvention.DB_OPERATION_GET,
|
31
|
+
"qdrant.search": SemanticConvention.DB_OPERATION_GET,
|
32
|
+
"qdrant.search_groups": SemanticConvention.DB_OPERATION_GET,
|
33
|
+
"qdrant.recommend": SemanticConvention.DB_OPERATION_GET,
|
34
|
+
"qdrant.query_points": SemanticConvention.DB_OPERATION_GET,
|
35
|
+
"qdrant.create_payload_index": SemanticConvention.DB_OPERATION_CREATE_INDEX,
|
36
|
+
}
|
37
|
+
|
38
|
+
def object_count(obj):
|
39
|
+
"""
|
40
|
+
Counts Length of object if it exists, Else returns 0.
|
41
|
+
"""
|
42
|
+
try:
|
43
|
+
return len(obj)
|
44
|
+
except (TypeError, AttributeError):
|
45
|
+
return 0
|
46
|
+
|
47
|
+
def set_server_address_and_port(instance):
|
48
|
+
"""
|
49
|
+
Extracts server address and port from Qdrant client instance.
|
50
|
+
|
51
|
+
Args:
|
52
|
+
instance: Qdrant client instance
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
tuple: (server_address, server_port)
|
56
|
+
"""
|
57
|
+
server_address = "localhost"
|
58
|
+
server_port = 6333
|
59
|
+
|
60
|
+
# Try to extract actual server info from Qdrant init_options
|
61
|
+
if hasattr(instance, "init_options") and instance.init_options:
|
62
|
+
init_options = instance.init_options
|
63
|
+
|
64
|
+
# Get URL and extract host/port from it
|
65
|
+
url = init_options.get("url", "")
|
66
|
+
if url:
|
67
|
+
try:
|
68
|
+
parsed = urlparse(url)
|
69
|
+
if parsed.hostname:
|
70
|
+
server_address = parsed.hostname
|
71
|
+
if parsed.port:
|
72
|
+
server_port = parsed.port
|
73
|
+
except Exception:
|
74
|
+
pass
|
75
|
+
|
76
|
+
# Also try direct port from init_options if URL parsing didnt work
|
77
|
+
if "port" in init_options and init_options["port"]:
|
78
|
+
server_port = init_options["port"]
|
79
|
+
|
80
|
+
return server_address, server_port
|
81
|
+
|
82
|
+
def common_qdrant_logic(scope, environment, application_name,
|
83
|
+
metrics, capture_message_content, disable_metrics, version,
|
84
|
+
instance=None, endpoint=None):
|
85
|
+
"""
|
86
|
+
Process Qdrant request and generate telemetry.
|
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_QDRANT,
|
92
|
+
scope._server_address, scope._server_port,
|
93
|
+
environment, application_name, version)
|
94
|
+
|
95
|
+
# Set DB operation specific attributes
|
96
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_NAME, scope._db_operation)
|
97
|
+
scope._span.set_attribute(SemanticConvention.DB_CLIENT_OPERATION_DURATION,
|
98
|
+
scope._end_time - scope._start_time)
|
99
|
+
|
100
|
+
# Handle collection management operations
|
101
|
+
if scope._db_operation in [SemanticConvention.DB_OPERATION_CREATE_COLLECTION,
|
102
|
+
SemanticConvention.DB_OPERATION_DELETE_COLLECTION,
|
103
|
+
SemanticConvention.DB_OPERATION_UPDATE_COLLECTION]:
|
104
|
+
collection_name = scope._kwargs.get("collection_name", "unknown")
|
105
|
+
|
106
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
107
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT,
|
108
|
+
f"Collection: {collection_name}")
|
109
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
110
|
+
f"{scope._db_operation} {collection_name}")
|
111
|
+
|
112
|
+
# Handle data insertion operations
|
113
|
+
elif scope._db_operation in [SemanticConvention.DB_OPERATION_INSERT,
|
114
|
+
SemanticConvention.DB_OPERATION_UPSERT]:
|
115
|
+
collection_name = scope._kwargs.get("collection_name", "unknown")
|
116
|
+
|
117
|
+
if endpoint == "qdrant.set_payload":
|
118
|
+
points = scope._kwargs.get("points", [])
|
119
|
+
payload = scope._kwargs.get("payload", {})
|
120
|
+
|
121
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
122
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(points))
|
123
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(points))
|
124
|
+
scope._span.set_attribute(SemanticConvention.DB_PAYLOAD_COUNT, object_count(payload))
|
125
|
+
|
126
|
+
# Set operation status if response available
|
127
|
+
if scope._response and hasattr(scope._response, "status"):
|
128
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
129
|
+
scope._response.status)
|
130
|
+
|
131
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
132
|
+
f"{scope._db_operation} {collection_name} "
|
133
|
+
f"points={object_count(points)} "
|
134
|
+
f"payload={object_count(payload)}")
|
135
|
+
|
136
|
+
elif endpoint in ["qdrant.upsert", "qdrant.upload_points"]:
|
137
|
+
points = scope._kwargs.get("points", [])
|
138
|
+
|
139
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
140
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(points))
|
141
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(points))
|
142
|
+
|
143
|
+
# Set operation status if response available
|
144
|
+
if scope._response and hasattr(scope._response, "status"):
|
145
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
146
|
+
scope._response.status)
|
147
|
+
|
148
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
149
|
+
f"{scope._db_operation} {collection_name} "
|
150
|
+
f"points={object_count(points)}")
|
151
|
+
|
152
|
+
# Handle data update operations
|
153
|
+
elif scope._db_operation == SemanticConvention.DB_OPERATION_UPDATE:
|
154
|
+
collection_name = scope._kwargs.get("collection_name", "unknown")
|
155
|
+
|
156
|
+
if endpoint == "qdrant.overwrite_payload":
|
157
|
+
points = scope._kwargs.get("points", [])
|
158
|
+
payload = scope._kwargs.get("payload", {})
|
159
|
+
|
160
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
161
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(points))
|
162
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(points))
|
163
|
+
scope._span.set_attribute(SemanticConvention.DB_PAYLOAD_COUNT, object_count(payload))
|
164
|
+
|
165
|
+
# Set operation status if response available
|
166
|
+
if scope._response and hasattr(scope._response, "status"):
|
167
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
168
|
+
scope._response.status)
|
169
|
+
|
170
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
171
|
+
f"{scope._db_operation} {collection_name} "
|
172
|
+
f"points={object_count(points)} "
|
173
|
+
f"payload={object_count(payload)}")
|
174
|
+
|
175
|
+
elif endpoint == "qdrant.update_vectors":
|
176
|
+
points = scope._kwargs.get("points", [])
|
177
|
+
|
178
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
179
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(points))
|
180
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(points))
|
181
|
+
|
182
|
+
# Set operation status if response available
|
183
|
+
if scope._response and hasattr(scope._response, "status"):
|
184
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
185
|
+
scope._response.status)
|
186
|
+
|
187
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
188
|
+
f"{scope._db_operation} {collection_name} "
|
189
|
+
f"points={object_count(points)}")
|
190
|
+
|
191
|
+
# Handle data deletion operations
|
192
|
+
elif scope._db_operation == SemanticConvention.DB_OPERATION_DELETE:
|
193
|
+
collection_name = scope._kwargs.get("collection_name", "unknown")
|
194
|
+
|
195
|
+
if endpoint in ["qdrant.delete_payload", "qdrant.delete_vectors"]:
|
196
|
+
points = scope._kwargs.get("points", [])
|
197
|
+
|
198
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
199
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(points))
|
200
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(points))
|
201
|
+
|
202
|
+
# Set operation status if response available
|
203
|
+
if scope._response and hasattr(scope._response, "status"):
|
204
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
205
|
+
scope._response.status)
|
206
|
+
|
207
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
208
|
+
f"{scope._db_operation} {collection_name} "
|
209
|
+
f"points={object_count(points)}")
|
210
|
+
|
211
|
+
elif endpoint in ["qdrant.clear_payload", "qdrant.delete"]:
|
212
|
+
points_selector = scope._kwargs.get("points_selector", [])
|
213
|
+
|
214
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
215
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(points_selector))
|
216
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(points_selector))
|
217
|
+
|
218
|
+
# Set operation status if response available
|
219
|
+
if scope._response and hasattr(scope._response, "status"):
|
220
|
+
scope._span.set_attribute(SemanticConvention.DB_OPERATION_STATUS,
|
221
|
+
scope._response.status)
|
222
|
+
|
223
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
224
|
+
f"{scope._db_operation} {collection_name} "
|
225
|
+
f"selector={object_count(points_selector)}")
|
226
|
+
|
227
|
+
# Handle query operations
|
228
|
+
elif scope._db_operation == SemanticConvention.DB_OPERATION_GET:
|
229
|
+
collection_name = scope._kwargs.get("collection_name", "unknown")
|
230
|
+
|
231
|
+
if endpoint == "qdrant.retrieve":
|
232
|
+
ids = scope._kwargs.get("ids", [])
|
233
|
+
|
234
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
235
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(ids))
|
236
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_COUNT, object_count(ids))
|
237
|
+
|
238
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
239
|
+
f"{scope._db_operation} {collection_name} ids={ids}")
|
240
|
+
|
241
|
+
elif endpoint == "qdrant.scroll":
|
242
|
+
scroll_filter = scope._kwargs.get("scroll_filter", {})
|
243
|
+
|
244
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
245
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(scroll_filter))
|
246
|
+
scope._span.set_attribute(SemanticConvention.DB_FILTER, str(scroll_filter))
|
247
|
+
|
248
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
249
|
+
f"{scope._db_operation} {collection_name} "
|
250
|
+
f"filter={scroll_filter}")
|
251
|
+
|
252
|
+
elif endpoint in ["qdrant.search", "qdrant.search_groups"]:
|
253
|
+
query_vector = scope._kwargs.get("query_vector", [])
|
254
|
+
limit = scope._kwargs.get("limit", 10)
|
255
|
+
|
256
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
257
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(query_vector))
|
258
|
+
scope._span.set_attribute(SemanticConvention.DB_VECTOR_QUERY_TOP_K, limit)
|
259
|
+
|
260
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
261
|
+
f"{scope._db_operation} {collection_name} "
|
262
|
+
f"limit={limit}")
|
263
|
+
|
264
|
+
elif endpoint == "qdrant.recommend":
|
265
|
+
positive = scope._kwargs.get("positive", [])
|
266
|
+
negative = scope._kwargs.get("negative", [])
|
267
|
+
|
268
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
269
|
+
query_content = f"positive:{positive} negative:{negative}"
|
270
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, query_content)
|
271
|
+
|
272
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
273
|
+
f"{scope._db_operation} {collection_name} "
|
274
|
+
f"positive={object_count(positive)} "
|
275
|
+
f"negative={object_count(negative)}")
|
276
|
+
|
277
|
+
elif endpoint == "qdrant.query_points":
|
278
|
+
query = scope._kwargs.get("query", {})
|
279
|
+
|
280
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
281
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, str(query))
|
282
|
+
|
283
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
284
|
+
f"{scope._db_operation} {collection_name} query={query}")
|
285
|
+
|
286
|
+
# Handle index operations
|
287
|
+
elif scope._db_operation == SemanticConvention.DB_OPERATION_CREATE_INDEX:
|
288
|
+
collection_name = scope._kwargs.get("collection_name", "unknown")
|
289
|
+
field_name = scope._kwargs.get("field_name", "unknown")
|
290
|
+
|
291
|
+
scope._span.set_attribute(SemanticConvention.DB_COLLECTION_NAME, collection_name)
|
292
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_TEXT, f"Field: {field_name}")
|
293
|
+
|
294
|
+
scope._span.set_attribute(SemanticConvention.DB_QUERY_SUMMARY,
|
295
|
+
f"{scope._db_operation} {collection_name} field={field_name}")
|
296
|
+
|
297
|
+
scope._span.set_status(Status(StatusCode.OK))
|
298
|
+
|
299
|
+
# Record metrics using helper
|
300
|
+
if not disable_metrics:
|
301
|
+
record_db_metrics(metrics, SemanticConvention.DB_SYSTEM_QDRANT,
|
302
|
+
scope._server_address, scope._server_port,
|
303
|
+
environment, application_name,
|
304
|
+
scope._start_time, scope._end_time)
|
305
|
+
|
306
|
+
def process_qdrant_response(response, db_operation, server_address, server_port,
|
307
|
+
environment, application_name, metrics, start_time, span,
|
308
|
+
capture_message_content, disable_metrics, version,
|
309
|
+
instance=None, args=None, endpoint=None, **kwargs):
|
310
|
+
"""
|
311
|
+
Process Qdrant response and generate telemetry.
|
312
|
+
"""
|
313
|
+
# Create scope object
|
314
|
+
scope = type("GenericScope", (), {})()
|
315
|
+
scope._span = span
|
316
|
+
scope._response = response
|
317
|
+
scope._db_operation = db_operation
|
318
|
+
scope._server_address = server_address
|
319
|
+
scope._server_port = server_port
|
320
|
+
scope._start_time = start_time
|
321
|
+
scope._kwargs = kwargs
|
322
|
+
|
323
|
+
# Process the response
|
324
|
+
common_qdrant_logic(scope, environment, application_name,
|
325
|
+
metrics, capture_message_content, disable_metrics, version,
|
326
|
+
instance=instance, endpoint=endpoint)
|
327
|
+
|
328
|
+
return response
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: openlit
|
3
|
-
Version: 1.34.
|
3
|
+
Version: 1.34.26
|
4
4
|
Summary: OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications and GPUs, facilitating the integration of observability into your GenAI-driven projects
|
5
5
|
License: Apache-2.0
|
6
6
|
Keywords: OpenTelemetry,otel,otlp,llm,tracing,openai,anthropic,claude,cohere,llm monitoring,observability,monitoring,gpt,Generative AI,chatGPT,gpu
|