@@ -31,6 +31,7 @@ import (
31
31
"github.com/seldonio/seldon-core/scheduler/v2/pkg/agent/modelscaling"
32
32
"github.com/seldonio/seldon-core/scheduler/v2/pkg/envoy/resources"
33
33
testing_utils2 "github.com/seldonio/seldon-core/scheduler/v2/pkg/internal/testing_utils"
34
+ "github.com/seldonio/seldon-core/scheduler/v2/pkg/metrics"
34
35
"github.com/seldonio/seldon-core/scheduler/v2/pkg/util"
35
36
)
36
37
@@ -98,9 +99,16 @@ type loadModelSateValue struct {
98
99
isSoft bool
99
100
}
100
101
102
+ type inferModelSateValue struct {
103
+ internalModelName string
104
+ method string
105
+ code string
106
+ }
107
+
101
108
type fakeMetricsHandler struct {
102
- modelLoadState map [string ]loadModelSateValue
103
- mu * sync.Mutex
109
+ modelLoadState map [string ]loadModelSateValue
110
+ modelInferState map [string ]inferModelSateValue
111
+ mu * sync.Mutex
104
112
}
105
113
106
114
func (f fakeMetricsHandler ) AddModelHistogramMetricsHandler (baseHandler http.HandlerFunc ) http.HandlerFunc {
@@ -112,6 +120,14 @@ func (f fakeMetricsHandler) HttpCodeToString(code int) string {
112
120
}
113
121
114
122
func (f fakeMetricsHandler ) AddModelInferMetrics (externalModelName string , internalModelName string , method string , elapsedTime float64 , code string ) {
123
+ f .mu .Lock ()
124
+ defer f .mu .Unlock ()
125
+
126
+ f .modelInferState [externalModelName ] = inferModelSateValue {
127
+ internalModelName : internalModelName ,
128
+ method : method ,
129
+ code : code ,
130
+ }
115
131
}
116
132
117
133
func (f fakeMetricsHandler ) AddLoadedModelMetrics (internalModelName string , memory uint64 , isLoad , isSoft bool ) {
@@ -130,8 +146,9 @@ func (f fakeMetricsHandler) AddServerReplicaMetrics(memory uint64, memoryWithOve
130
146
131
147
func newFakeMetricsHandler () fakeMetricsHandler {
132
148
return fakeMetricsHandler {
133
- modelLoadState : map [string ]loadModelSateValue {},
134
- mu : & sync.Mutex {},
149
+ modelLoadState : map [string ]loadModelSateValue {},
150
+ modelInferState : map [string ]inferModelSateValue {},
151
+ mu : & sync.Mutex {},
135
152
}
136
153
}
137
154
@@ -141,7 +158,7 @@ func (f fakeMetricsHandler) UnaryServerInterceptor() func(ctx context.Context, r
141
158
}
142
159
}
143
160
144
- func setupReverseProxy (logger log.FieldLogger , numModels int , modelPrefix string , rpPort , serverPort int ) * reverseHTTPProxy {
161
+ func setupReverseProxy (logger log.FieldLogger , numModels int , modelPrefix string , rpPort , serverPort int , metricsHandler metrics. AgentMetricsHandler ) * reverseHTTPProxy {
145
162
v2Client := testing_utils .NewV2RestClientForTest ("localhost" , serverPort , logger )
146
163
localCacheManager := setupLocalTestManager (numModels , modelPrefix , v2Client , numModels - 2 , 1 )
147
164
modelScalingStatsCollector := modelscaling .NewDataPlaneStatsCollector (
@@ -153,7 +170,7 @@ func setupReverseProxy(logger log.FieldLogger, numModels int, modelPrefix string
153
170
"localhost" ,
154
171
uint (serverPort ),
155
172
uint (rpPort ),
156
- fakeMetricsHandler {} ,
173
+ metricsHandler ,
157
174
modelScalingStatsCollector ,
158
175
)
159
176
rp .SetState (localCacheManager )
@@ -166,34 +183,51 @@ func TestReverseProxySmoke(t *testing.T) {
166
183
logger .SetLevel (log .DebugLevel )
167
184
168
185
type test struct {
169
- name string
170
- modelToLoad string
171
- modelToRequest string
172
- statusCode int
173
- isLoadedonServer bool
186
+ name string
187
+ modelToLoad string
188
+ modelToRequest string
189
+ modelExternalHeader string
190
+ expectedModelExternalTag string
191
+ statusCode int
192
+ isLoadedonServer bool
174
193
}
175
194
176
195
tests := []test {
177
196
{
178
- name : "model exists" ,
179
- modelToLoad : "foo" ,
180
- modelToRequest : "foo" ,
181
- statusCode : http .StatusOK ,
182
- isLoadedonServer : true ,
197
+ name : "model exists" ,
198
+ modelToLoad : "foo_1" ,
199
+ modelToRequest : "foo_1" ,
200
+ modelExternalHeader : "foo" ,
201
+ expectedModelExternalTag : "foo" ,
202
+ statusCode : http .StatusOK ,
203
+ isLoadedonServer : true ,
183
204
},
184
205
{
185
- name : "model exists on agent but not loaded on server" ,
186
- modelToLoad : "foo" ,
187
- modelToRequest : "foo" ,
188
- statusCode : http .StatusOK ,
189
- isLoadedonServer : false ,
206
+ name : "model exists, part of experiment" ,
207
+ modelToLoad : "foo_1" ,
208
+ modelToRequest : "foo_1" ,
209
+ modelExternalHeader : "foo-experiment.experiment" ,
210
+ expectedModelExternalTag : "foo" ,
211
+ statusCode : http .StatusOK ,
212
+ isLoadedonServer : true ,
190
213
},
191
214
{
192
- name : "model does not exists" ,
193
- modelToLoad : "foo" ,
194
- modelToRequest : "foo2" ,
195
- statusCode : http .StatusNotFound ,
196
- isLoadedonServer : false ,
215
+ name : "model exists on agent but not loaded on server" ,
216
+ modelToLoad : "foo_1" ,
217
+ modelToRequest : "foo_1" ,
218
+ modelExternalHeader : "foo" ,
219
+ expectedModelExternalTag : "foo" ,
220
+ statusCode : http .StatusOK ,
221
+ isLoadedonServer : false ,
222
+ },
223
+ {
224
+ name : "model does not exists" ,
225
+ modelToLoad : "foo_1" ,
226
+ modelToRequest : "foo2_1" ,
227
+ modelExternalHeader : "foo2" ,
228
+ expectedModelExternalTag : "foo2" ,
229
+ statusCode : http .StatusNotFound ,
230
+ isLoadedonServer : false ,
197
231
},
198
232
}
199
233
@@ -217,7 +251,8 @@ func TestReverseProxySmoke(t *testing.T) {
217
251
if err != nil {
218
252
t .Fatal (err )
219
253
}
220
- rpHTTP := setupReverseProxy (logger , 3 , test .modelToLoad , rpPort , serverPort )
254
+ fakeMetricsHandler := newFakeMetricsHandler ()
255
+ rpHTTP := setupReverseProxy (logger , 3 , test .modelToLoad , rpPort , serverPort , fakeMetricsHandler )
221
256
err = rpHTTP .Start ()
222
257
g .Expect (err ).To (BeNil ())
223
258
time .Sleep (500 * time .Millisecond )
@@ -237,7 +272,7 @@ func TestReverseProxySmoke(t *testing.T) {
237
272
req , err := http .NewRequest (http .MethodPost , url , nil )
238
273
g .Expect (err ).To (BeNil ())
239
274
req .Header .Set ("contentType" , "application/json" )
240
- req .Header .Set (resources .SeldonModelHeader , test .modelToRequest )
275
+ req .Header .Set (resources .SeldonModelHeader , test .modelExternalHeader )
241
276
req .Header .Set (resources .SeldonInternalModelHeader , test .modelToRequest )
242
277
resp , err := http .DefaultClient .Do (req )
243
278
g .Expect (err ).To (BeNil ())
@@ -254,9 +289,16 @@ func TestReverseProxySmoke(t *testing.T) {
254
289
if test .statusCode == http .StatusOK {
255
290
g .Expect (rpHTTP .modelScalingStatsCollector .ModelLagStats .Get (test .modelToRequest )).To (Equal (uint32 (0 )))
256
291
g .Expect (rpHTTP .modelScalingStatsCollector .ModelLastUsedStats .Get (test .modelToRequest )).Should (BeNumerically ("<=" , time .Now ().Unix ())) // only triggered when we get results back
257
-
258
292
}
259
293
294
+ // test infer metrics
295
+ g .Expect (fakeMetricsHandler .modelInferState [test .expectedModelExternalTag ].internalModelName ).To (Equal (test .modelToRequest ))
296
+ g .Expect (fakeMetricsHandler .modelInferState [test .expectedModelExternalTag ].method ).To (Equal ("rest" ))
297
+ if test .statusCode == http .StatusOK {
298
+ g .Expect (fakeMetricsHandler .modelInferState [test .expectedModelExternalTag ].code ).To (Equal ("200" ))
299
+ } else {
300
+ g .Expect (fakeMetricsHandler .modelInferState [test .expectedModelExternalTag ].code ).To (Equal ("404" ))
301
+ }
260
302
g .Expect (rpHTTP .Ready ()).To (BeTrue ())
261
303
_ = rpHTTP .Stop ()
262
304
g .Expect (rpHTTP .Ready ()).To (BeFalse ())
@@ -273,7 +315,8 @@ func TestReverseEarlyStop(t *testing.T) {
273
315
logger := log .New ()
274
316
logger .SetLevel (log .DebugLevel )
275
317
276
- rpHTTP := setupReverseProxy (logger , 0 , "dummy" , 1 , 1 )
318
+ fakeMetricsHandler := newFakeMetricsHandler ()
319
+ rpHTTP := setupReverseProxy (logger , 0 , "dummy" , 1 , 1 , fakeMetricsHandler )
277
320
err := rpHTTP .Stop ()
278
321
g .Expect (err ).To (BeNil ())
279
322
ready := rpHTTP .Ready ()
0 commit comments