1
+ import time
1
2
from opentelemetry .instrumentation .milvus .utils import dont_throw
2
3
from opentelemetry .semconv .trace import SpanAttributes
3
4
from opentelemetry .semconv .attributes .error_attributes import ERROR_TYPE
23
24
def _with_tracer_wrapper (func ):
24
25
"""Helper for providing tracer for wrapper functions."""
25
26
26
- def _with_tracer (tracer , to_wrap ):
27
+ def _with_tracer (
28
+ tracer ,
29
+ query_duration_metric ,
30
+ distance_metric ,
31
+ insert_units_metric ,
32
+ upsert_units_metric ,
33
+ delete_units_metric ,
34
+ to_wrap ):
27
35
def wrapper (wrapped , instance , args , kwargs ):
28
- return func (tracer , to_wrap , wrapped , instance , args , kwargs )
36
+ return func (
37
+ tracer ,
38
+ query_duration_metric ,
39
+ distance_metric ,
40
+ insert_units_metric ,
41
+ upsert_units_metric ,
42
+ delete_units_metric ,
43
+ to_wrap ,
44
+ wrapped ,
45
+ args ,
46
+ kwargs )
29
47
30
48
return wrapper
31
49
@@ -40,50 +58,82 @@ def _set_span_attribute(span, name, value):
40
58
41
59
42
60
@_with_tracer_wrapper
43
- def _wrap (tracer , to_wrap , wrapped , instance , args , kwargs ):
61
+ def _wrap (
62
+ tracer ,
63
+ query_duration_metric ,
64
+ distance_metric ,
65
+ insert_units_metric ,
66
+ upsert_units_metric ,
67
+ delete_units_metric ,
68
+ to_wrap ,
69
+ wrapped ,
70
+ args ,
71
+ kwargs
72
+ ):
44
73
"""Instruments and calls every function defined in TO_WRAP."""
45
74
if context_api .get_value (_SUPPRESS_INSTRUMENTATION_KEY ):
46
75
return wrapped (* args , ** kwargs )
47
76
77
+ method = to_wrap .get ("method" )
48
78
name = to_wrap .get ("span_name" )
49
79
with tracer .start_as_current_span (name ) as span :
50
80
span .set_attribute (SpanAttributes .DB_SYSTEM , "milvus" )
51
81
span .set_attribute (SpanAttributes .DB_OPERATION , to_wrap .get ("method" ))
52
82
53
- if to_wrap . get ( " method" ) == "insert" :
83
+ if method == "insert" :
54
84
_set_insert_attributes (span , kwargs )
55
- elif to_wrap . get ( " method" ) == "upsert" :
85
+ elif method == "upsert" :
56
86
_set_upsert_attributes (span , kwargs )
57
- elif to_wrap . get ( " method" ) == "delete" :
87
+ elif method == "delete" :
58
88
_set_delete_attributes (span , kwargs )
59
- elif to_wrap . get ( " method" ) == "search" :
89
+ elif method == "search" :
60
90
_set_search_attributes (span , kwargs )
61
- elif to_wrap . get ( " method" ) == "get" :
91
+ elif method == "get" :
62
92
_set_get_attributes (span , kwargs )
63
- elif to_wrap . get ( " method" ) == "query" :
93
+ elif method == "query" :
64
94
_set_query_attributes (span , kwargs )
65
- elif to_wrap . get ( " method" ) == "create_collection" :
95
+ elif method == "create_collection" :
66
96
_set_create_collection_attributes (span , kwargs )
67
- elif to_wrap . get ( " method" ) == "hybrid_search" :
97
+ elif method == "hybrid_search" :
68
98
_set_hybrid_search_attributes (span , kwargs )
69
99
70
100
try :
101
+ start_time = time .time ()
71
102
return_value = wrapped (* args , ** kwargs )
72
- if to_wrap .get ("method" ) == "query" :
103
+ end_time = time .time ()
104
+ if method == "query" :
73
105
_add_query_result_events (span , return_value )
74
106
75
- if (
76
- to_wrap .get ("method" ) == "search"
77
- or to_wrap .get ("method" ) == "hybrid_search"
78
- ):
107
+ if method == "search" or method == "hybrid_search" :
79
108
_add_search_result_events (span , return_value )
109
+
80
110
except Exception as e :
81
111
error_type = code_to_error_type .get (
82
112
getattr (e , "code" , None ), type (e ).__name__
83
113
)
84
114
span .set_attribute (ERROR_TYPE , error_type )
85
115
raise
86
116
117
+ shared_attributes = {
118
+ SpanAttributes .DB_SYSTEM : "milvus" ,
119
+ SpanAttributes .DB_OPERATION : method ,
120
+ }
121
+ duration = end_time - start_time
122
+ if duration > 0 and query_duration_metric and method == "query" :
123
+ query_duration_metric .record (duration , shared_attributes )
124
+
125
+ if return_value :
126
+ if method == "search" or method == "hybrid_search" :
127
+ set_search_response (distance_metric , shared_attributes , return_value )
128
+
129
+ _set_response_attributes (
130
+ insert_units_metric ,
131
+ upsert_units_metric ,
132
+ delete_units_metric ,
133
+ shared_attributes ,
134
+ return_value ,
135
+ )
136
+
87
137
return return_value
88
138
89
139
@@ -118,6 +168,30 @@ def count_or_none(obj):
118
168
return None
119
169
120
170
171
+ @dont_throw
172
+ def _set_response_attributes (
173
+ insert_units_metric ,
174
+ upsert_units_metric ,
175
+ delete_units_metric ,
176
+ shared_attributes ,
177
+ response
178
+ ):
179
+ if not isinstance (response , dict ):
180
+ return
181
+
182
+ if 'upsert_count' in response :
183
+ upsert_count = response ['upsert_count' ] or 0
184
+ upsert_units_metric .add (upsert_count , shared_attributes )
185
+
186
+ if 'insert_count' in response :
187
+ insert_count = response ['insert_count' ] or 0
188
+ insert_units_metric .add (insert_count , shared_attributes )
189
+
190
+ if 'delete_count' in response :
191
+ delete_count = response ['delete_count' ] or 0
192
+ delete_units_metric .add (delete_count , shared_attributes )
193
+
194
+
121
195
@dont_throw
122
196
def _set_create_collection_attributes (span , kwargs ):
123
197
_set_span_attribute (
@@ -443,3 +517,13 @@ def _set_delete_attributes(span, kwargs):
443
517
AISpanAttributes .MILVUS_DELETE_FILTER ,
444
518
_encode_filter (kwargs .get ("filter" )),
445
519
)
520
+
521
+
522
+ @dont_throw
523
+ def set_search_response (distance_metric , shared_attributes , response ):
524
+ for query_result in response :
525
+ for match in query_result :
526
+ distance = match .get ("distance" )
527
+
528
+ if distance_metric and distance is not None :
529
+ distance_metric .record (distance , shared_attributes )
0 commit comments