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.
- openlit/__helpers.py +38 -0
- openlit/__init__.py +22 -155
- openlit/_instrumentors.py +144 -0
- openlit/guard/all.py +3 -3
- openlit/instrumentation/astra/__init__.py +71 -159
- openlit/instrumentation/astra/astra.py +32 -22
- openlit/instrumentation/astra/async_astra.py +32 -22
- openlit/instrumentation/astra/utils.py +263 -88
- openlit/instrumentation/chroma/utils.py +2 -2
- openlit/instrumentation/controlflow/controlflow.py +2 -2
- openlit/instrumentation/embedchain/embedchain.py +4 -4
- openlit/instrumentation/groq/__init__.py +4 -4
- openlit/instrumentation/haystack/__init__.py +57 -28
- openlit/instrumentation/haystack/async_haystack.py +54 -0
- openlit/instrumentation/haystack/haystack.py +35 -65
- openlit/instrumentation/haystack/utils.py +377 -0
- openlit/instrumentation/julep/async_julep.py +2 -2
- openlit/instrumentation/julep/julep.py +2 -2
- openlit/instrumentation/langchain_community/utils.py +2 -2
- openlit/instrumentation/llamaindex/__init__.py +165 -37
- openlit/instrumentation/llamaindex/async_llamaindex.py +53 -0
- openlit/instrumentation/llamaindex/llamaindex.py +32 -64
- openlit/instrumentation/llamaindex/utils.py +412 -0
- openlit/instrumentation/mem0/mem0.py +2 -2
- openlit/instrumentation/milvus/__init__.py +30 -68
- openlit/instrumentation/milvus/milvus.py +34 -161
- openlit/instrumentation/milvus/utils.py +276 -0
- openlit/instrumentation/openai/__init__.py +24 -24
- openlit/instrumentation/openai/utils.py +10 -4
- openlit/instrumentation/pinecone/utils.py +2 -2
- openlit/instrumentation/qdrant/utils.py +2 -2
- openlit/instrumentation/together/__init__.py +8 -8
- openlit/semcov/__init__.py +79 -0
- {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/METADATA +1 -1
- {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/RECORD +37 -31
- {openlit-1.34.26.dist-info → openlit-1.34.28.dist-info}/LICENSE +0 -0
- {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
|
7
|
-
from opentelemetry.trace import SpanKind
|
8
|
-
from opentelemetry
|
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.
|
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
|
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
|
-
|
16
|
+
tracer, pricing_info, capture_message_content, metrics, disable_metrics):
|
29
17
|
"""
|
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.
|
18
|
+
Generates a telemetry wrapper for Milvus function calls.
|
47
19
|
"""
|
48
|
-
|
49
20
|
def wrapper(wrapped, instance, args, kwargs):
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
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
|
"""
|