@@ -44,6 +44,17 @@ type Config struct {
4444
4545type StatusType int
4646
47+ var statusTypes = map [StatusType ]string {
48+ StatusStopped : "stopped" ,
49+ StatusSpawning : "spawning" ,
50+ StatusRunning : "running" ,
51+ StatusStopping : "stopping" ,
52+ }
53+
54+ func (s StatusType ) MarshalJSON () ([]byte , error ) {
55+ return []byte (statusTypes [s ]), nil
56+ }
57+
4758const (
4859 StatusStopped StatusType = iota
4960 StatusSpawning
@@ -183,15 +194,15 @@ func (ts *Statistics) Calculate() {
183194}
184195
185196type LoadTest struct {
186- Config Config
187- Status StatusType
188-
189- Users map [int64 ]User
190- StatusChan chan StatusType
191- UserStatusChan chan User
192- TaskRunChan chan * TaskRun
193- Stats Statistics
194- Log * log.Logger
197+ Config Config `json:"config"`
198+ Status StatusType `json:"status"`
199+
200+ Users map [int64 ]User `json:"-"`
201+ StatusChan chan StatusType `json:"-"`
202+ UserStatusChan chan User `json:"-"`
203+ TaskRunChan chan * TaskRun `json:"-"`
204+ Stats * Statistics `json:"stats"`
205+ Log * log.Logger `json:"-"`
195206}
196207
197208func NewConfigFromFlags () Config {
@@ -260,7 +271,7 @@ func (lt *LoadTest) handleTaskRun(tr *TaskRun) {
260271}
261272
262273func (lt * LoadTest ) spawnUsers (entryTask * Task ) {
263- for i := 0 ; i < lt .Config .NumUsers ; i ++ {
274+ for i := len ( lt . Users ) ; i < lt .Config .NumUsers ; i ++ {
264275 // Create a new User instance
265276 var u User
266277 uv := reflect .ValueOf (lt .Config .UserType )
@@ -285,6 +296,9 @@ func (lt *LoadTest) spawnUsers(entryTask *Task) {
285296 u .SetContext (ctx )
286297
287298 go func () {
299+ u .SetStatus (UserStatusSpawning )
300+ lt .UserStatusChan <- u
301+
288302 // Sleep according to user ID to ramp up the user spawns
289303 preSpawnSleepTime := u .ID () / int64 (lt .Config .NumSpawnPerSecond )
290304 time .Sleep (time .Second * time .Duration (preSpawnSleepTime ))
@@ -294,7 +308,7 @@ func (lt *LoadTest) spawnUsers(entryTask *Task) {
294308 u .SetStatus (UserStatusRunning )
295309 lt .UserStatusChan <- u
296310
297- for lt .Status != StatusStopping {
311+ for lt .Status != StatusStopping && int ( u . ID ()) < lt . Config . NumUsers {
298312 u .Tick ()
299313 u .Sleep ()
300314 }
@@ -308,7 +322,7 @@ func (lt *LoadTest) spawnUsers(entryTask *Task) {
308322func (lt * LoadTest ) handleStatus (status StatusType , entryTask * Task ) {
309323 switch status {
310324 case StatusSpawning :
311- if lt .Status != StatusStopped {
325+ if lt .Status != StatusStopped && lt . Status != StatusRunning {
312326 lt .Log .Printf ("invalid state change from %d to %d\n " , lt .Status , status )
313327 return
314328 }
@@ -326,6 +340,9 @@ func (lt *LoadTest) handleStatus(status StatusType, entryTask *Task) {
326340}
327341
328342func (lt * LoadTest ) handleUserStatus (u User ) {
343+ lt .Log .Printf ("user status changed to %s on user %d\n " , u .Status (), u .ID ())
344+
345+ prevLen := len (lt .Users )
329346 if u .Status () == UserStatusRunning {
330347 lt .Users [u .ID ()] = u
331348 } else if u .Status () == UserStatusStopped {
@@ -336,7 +353,7 @@ func (lt *LoadTest) handleUserStatus(u User) {
336353 lt .Stats .NumUsers = len (lt .Users )
337354 lt .Stats .Unlock ()
338355
339- if lt . Status == StatusSpawning && len (lt .Users ) == lt .Config .NumUsers {
356+ if prevLen != len ( lt . Users ) && len (lt .Users ) == lt .Config .NumUsers {
340357 lt .Stats .Lock ()
341358 lt .Stats .StartTime = time .Now ()
342359 lt .Stats .Unlock ()
@@ -398,21 +415,25 @@ func (lt *LoadTest) Run(entryTask *Task) {
398415 <- c
399416}
400417
418+ func NewStatistics () * Statistics {
419+ return & Statistics {
420+ Tasks : make (map [string ]* TaskStats ),
421+ RPSMap : make (map [int64 ]int64 ),
422+ CurrentRPS : 0 ,
423+ AverageDuration : 0 ,
424+ }
425+ }
426+
401427func NewLoadTest (config Config ) * LoadTest {
402428 return & LoadTest {
403429 Config : config ,
404430 Status : StatusStopped ,
405431 Users : make (map [int64 ]User , config .NumUsers ),
406432 StatusChan : make (chan StatusType ),
407433 UserStatusChan : make (chan User , config .NumUsers ),
408- Stats : Statistics {
409- Tasks : make (map [string ]* TaskStats ),
410- RPSMap : make (map [int64 ]int64 ),
411- CurrentRPS : 0 ,
412- AverageDuration : 0 ,
413- },
414- TaskRunChan : make (chan * TaskRun , config .NumUsers ),
415- Log : log .New (config .LogOutput , config .LogPrefix , config .LogFlags ),
434+ Stats : NewStatistics (),
435+ TaskRunChan : make (chan * TaskRun , config .NumUsers ),
436+ Log : log .New (config .LogOutput , config .LogPrefix , config .LogFlags ),
416437 }
417438}
418439
0 commit comments