36
36
import tritonclient .grpc as grpcclient
37
37
import tritonclient .http as httpclient
38
38
39
- EXPECTED_NUM_SPANS = 10
39
+ EXPECTED_NUM_SPANS = 16
40
40
41
41
42
42
class OpenTelemetryTest (tu .TestResultCollector ):
@@ -50,68 +50,66 @@ def setUp(self):
50
50
else :
51
51
break
52
52
53
- data = data .split (' \n ' )
53
+ data = data .split (" \n " )
54
54
full_spans = [
55
- entry .split ('POST' )[0 ]
56
- for entry in data
57
- if "resource_spans" in entry
55
+ entry .split ("POST" )[0 ] for entry in data if "resource_spans" in entry
58
56
]
59
57
self .spans = []
58
+ self .resource_attributes = []
60
59
for span in full_spans :
61
60
span = json .loads (span )
62
- self .spans .append (
63
- span ["resource_spans" ][0 ]['scope_spans' ][0 ]['spans' ][0 ])
61
+ self .spans .append (span ["resource_spans" ][0 ]["scope_spans" ][0 ]["spans" ][0 ])
62
+ self .resource_attributes .append (
63
+ span ["resource_spans" ][0 ]["resource" ]["attributes" ]
64
+ )
64
65
65
66
self .simple_model_name = "simple"
66
67
self .ensemble_model_name = "ensemble_add_sub_int32_int32_int32"
68
+ self .bls_model_name = "bls_simple"
67
69
self .root_span = "InferRequest"
68
70
69
71
def _check_events (self , span_name , events ):
70
- root_events_http = \
71
- [ "HTTP_RECV_START" ,
72
- "HTTP_RECV_END" ,
73
- "INFER_RESPONSE_COMPLETE" ,
74
- "HTTP_SEND_START" ,
75
- "HTTP_SEND_END" ]
76
- root_events_grpc = \
77
- [ "GRPC_WAITREAD_START" ,
78
- "GRPC_WAITREAD_END " ,
79
- "INFER_RESPONSE_COMPLETE " ,
80
- "GRPC_SEND_START " ,
81
- "GRPC_SEND_END" ]
82
- request_events = \
83
- [ "REQUEST_START" ,
84
- "QUEUE_START" ,
85
- "REQUEST_END" ]
86
- compute_events = \
87
- [ "COMPUTE_START " ,
88
- "COMPUTE_INPUT_END " ,
89
- "COMPUTE_OUTPUT_START " ,
90
- "COMPUTE_END" ]
72
+ root_events_http = [
73
+ "HTTP_RECV_START" ,
74
+ "HTTP_RECV_END" ,
75
+ "INFER_RESPONSE_COMPLETE" ,
76
+ "HTTP_SEND_START" ,
77
+ "HTTP_SEND_END" ,
78
+ ]
79
+ root_events_grpc = [
80
+ "GRPC_WAITREAD_START " ,
81
+ "GRPC_WAITREAD_END " ,
82
+ "INFER_RESPONSE_COMPLETE " ,
83
+ "GRPC_SEND_START" ,
84
+ "GRPC_SEND_END" ,
85
+ ]
86
+ request_events = [ "REQUEST_START" , "QUEUE_START" , "REQUEST_END" ]
87
+ compute_events = [
88
+ "COMPUTE_START" ,
89
+ "COMPUTE_INPUT_END " ,
90
+ "COMPUTE_OUTPUT_START " ,
91
+ "COMPUTE_END " ,
92
+ ]
91
93
92
94
if span_name == "compute" :
93
95
# Check that all compute related events (and only them)
94
96
# are recorded in compute span
95
97
self .assertTrue (all (entry in events for entry in compute_events ))
96
98
self .assertFalse (all (entry in events for entry in request_events ))
97
99
self .assertFalse (
98
- all (entry in events
99
- for entry in root_events_http + root_events_grpc ) )
100
+ all (entry in events for entry in root_events_http + root_events_grpc )
101
+ )
100
102
101
103
elif span_name == self .root_span :
102
104
# Check that root span has INFER_RESPONSE_COMPLETE, _RECV/_WAITREAD
103
105
# and _SEND events (and only them)
104
106
if "HTTP" in events :
105
- self .assertTrue (
106
- all (entry in events for entry in root_events_http ))
107
- self .assertFalse (
108
- all (entry in events for entry in root_events_grpc ))
107
+ self .assertTrue (all (entry in events for entry in root_events_http ))
108
+ self .assertFalse (all (entry in events for entry in root_events_grpc ))
109
109
110
110
elif "GRPC" in events :
111
- self .assertTrue (
112
- all (entry in events for entry in root_events_grpc ))
113
- self .assertFalse (
114
- all (entry in events for entry in root_events_http ))
111
+ self .assertTrue (all (entry in events for entry in root_events_grpc ))
112
+ self .assertFalse (all (entry in events for entry in root_events_http ))
115
113
self .assertFalse (all (entry in events for entry in request_events ))
116
114
self .assertFalse (all (entry in events for entry in compute_events ))
117
115
@@ -120,17 +118,20 @@ def _check_events(self, span_name, events):
120
118
# are recorded in request span
121
119
self .assertTrue (all (entry in events for entry in request_events ))
122
120
self .assertFalse (
123
- all (entry in events
124
- for entry in root_events_http + root_events_grpc ) )
121
+ all (entry in events for entry in root_events_http + root_events_grpc )
122
+ )
125
123
self .assertFalse (all (entry in events for entry in compute_events ))
126
124
127
125
def _check_parent (self , child_span , parent_span ):
128
126
# Check that child and parent span have the same trace_id
129
127
# and child's `parent_span_id` is the same as parent's `span_id`
130
- self .assertEqual (child_span ['trace_id' ], parent_span ['trace_id' ])
131
- self .assertIn ('parent_span_id' , child_span ,
132
- "child span does not have parent span id specified" )
133
- self .assertEqual (child_span ['parent_span_id' ], parent_span ['span_id' ])
128
+ self .assertEqual (child_span ["trace_id" ], parent_span ["trace_id" ])
129
+ self .assertIn (
130
+ "parent_span_id" ,
131
+ child_span ,
132
+ "child span does not have parent span id specified" ,
133
+ )
134
+ self .assertEqual (child_span ["parent_span_id" ], parent_span ["span_id" ])
134
135
135
136
def test_spans (self ):
136
137
parsed_spans = []
@@ -141,16 +142,18 @@ def test_spans(self):
141
142
self ._check_events (span_name , json .dumps (span ["events" ]))
142
143
parsed_spans .append (span_name )
143
144
144
- # There should be 6 spans in total:
145
- # 3 for http request, 3 for grpc request, 4 for ensemble
146
- self .assertEqual (len (self .spans ), 10 )
147
- # We should have 3 compute spans
148
- self .assertEqual (parsed_spans .count ("compute" ), 3 )
149
- # 4 request spans (3 named simple - same as our model name, 1 ensemble)
150
- self .assertEqual (parsed_spans .count (self .simple_model_name ), 3 )
151
- self .assertEqual (parsed_spans .count (self .ensemble_model_name ), 1 )
152
- # 3 root spans
153
- self .assertEqual (parsed_spans .count (self .root_span ), 3 )
145
+ # There should be 16 spans in total:
146
+ # 3 for http request, 3 for grpc request, 4 for ensemble, 6 for bls
147
+ self .assertEqual (len (self .spans ), EXPECTED_NUM_SPANS )
148
+ # We should have 5 compute spans
149
+ self .assertEqual (parsed_spans .count ("compute" ), 5 )
150
+ # 7 request spans
151
+ # (4 named simple - same as our model name, 2 ensemble, 1 bls)
152
+ self .assertEqual (parsed_spans .count (self .simple_model_name ), 4 )
153
+ self .assertEqual (parsed_spans .count (self .ensemble_model_name ), 2 )
154
+ self .assertEqual (parsed_spans .count (self .bls_model_name ), 1 )
155
+ # 4 root spans
156
+ self .assertEqual (parsed_spans .count (self .root_span ), 4 )
154
157
155
158
def test_nested_spans (self ):
156
159
# First 3 spans in `self.spans` belong to HTTP request
@@ -162,27 +165,41 @@ def test_nested_spans(self):
162
165
self ._check_parent (child , parent )
163
166
164
167
# root_span should not have `parent_span_id` field
165
- self .assertNotIn ('parent_span_id' , self .spans [2 ],
166
- "root span has a parent_span_id specified" )
168
+ self .assertNotIn (
169
+ "parent_span_id" , self .spans [2 ], "root span has a parent_span_id specified"
170
+ )
167
171
168
172
# Next 3 spans in `self.spans` belong to GRPC request
169
173
# Order of spans and their relationship described earlier
170
174
for child , parent in zip (self .spans [3 :6 ], self .spans [4 :6 ]):
171
175
self ._check_parent (child , parent )
172
176
173
177
# root_span should not have `parent_span_id` field
174
- self .assertNotIn ('parent_span_id' , self .spans [5 ],
175
- "root span has a parent_span_id specified" )
178
+ self .assertNotIn (
179
+ "parent_span_id" , self .spans [5 ], "root span has a parent_span_id specified"
180
+ )
176
181
177
182
# Final 4 spans in `self.spans` belong to ensemble request
178
183
# Order of spans: compute span - request span - request span - root span
179
184
for child , parent in zip (self .spans [6 :10 ], self .spans [7 :10 ]):
180
185
self ._check_parent (child , parent )
181
186
182
187
# root_span should not have `parent_span_id` field
183
- self .assertNotIn ('parent_span_id' , self .spans [9 ],
184
- "root span has a parent_span_id specified" )
185
-
188
+ self .assertNotIn (
189
+ "parent_span_id" , self .spans [9 ], "root span has a parent_span_id specified"
190
+ )
191
+
192
+ def test_resource_attributes (self ):
193
+ test_attribute_entry = "{{'key': {k}, 'value': {{'string_value': {v}}}}}"
194
+ for attribute in self .resource_attributes :
195
+ self .assertIn (
196
+ test_attribute_entry .format (k = "'test.key'" , v = "'test.value'" ),
197
+ str (attribute ),
198
+ )
199
+ self .assertIn (
200
+ test_attribute_entry .format (k = "'service.name'" , v = "'test_triton'" ),
201
+ str (attribute ),
202
+ )
186
203
187
204
188
205
def prepare_data (client ):
@@ -201,11 +218,12 @@ def prepare_data(client):
201
218
202
219
203
220
def prepare_traces ():
204
-
205
- triton_client_http = httpclient .InferenceServerClient ("localhost:8000" ,
206
- verbose = True )
207
- triton_client_grpc = grpcclient .InferenceServerClient ("localhost:8001" ,
208
- verbose = True )
221
+ triton_client_http = httpclient .InferenceServerClient (
222
+ "localhost:8000" , verbose = True
223
+ )
224
+ triton_client_grpc = grpcclient .InferenceServerClient (
225
+ "localhost:8001" , verbose = True
226
+ )
209
227
inputs = prepare_data (httpclient )
210
228
triton_client_http .infer ("simple" , inputs )
211
229
@@ -215,16 +233,16 @@ def prepare_traces():
215
233
inputs = prepare_data (httpclient )
216
234
triton_client_http .infer ("ensemble_add_sub_int32_int32_int32" , inputs )
217
235
236
+ send_bls_request (model_name = "ensemble_add_sub_int32_int32_int32" )
218
237
219
- def send_bls_request ():
220
238
239
+ def send_bls_request (model_name = "simple" ):
221
240
with httpclient .InferenceServerClient ("localhost:8000" ) as client :
222
-
223
241
inputs = prepare_data (httpclient )
224
242
inputs .append (httpclient .InferInput ("MODEL_NAME" , [1 ], "BYTES" ))
225
- inputs [2 ].set_data_from_numpy (np .array (["simple" ], dtype = np .object_ ))
243
+ inputs [2 ].set_data_from_numpy (np .array ([model_name ], dtype = np .object_ ))
226
244
client .infer ("bls_simple" , inputs )
227
245
228
246
229
- if __name__ == ' __main__' :
247
+ if __name__ == " __main__" :
230
248
unittest .main ()
0 commit comments