-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathsimulator_finished.go
More file actions
116 lines (95 loc) · 2.7 KB
/
simulator_finished.go
File metadata and controls
116 lines (95 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// +build !active_file
package src
import (
"container/list"
"math"
"math/rand"
"time"
)
type User struct {
UserID string
CurrentPage *Page
LastChange time.Time
}
type Event struct {
Timestamp int64 `json:"unix_timestamp"`
PageTime float64 `json:"page_time_seconds,omitempty"`
Referrer string `json:"referrer,omitempty"`
UserID string `json:"user_id"`
Path string `json:"path"`
}
func (s *Simulator) Run() error {
users := list.New()
events := s.producer.TopicEncoder("events")
for s.Running() {
time.Sleep(JitterDuration(time.Second, 200*time.Millisecond))
unixNow := time.Now().Unix()
// create a random number of new users
if users.Len() < s.config.MaxUsersPerThread {
// figure out the max number of users we can create
maxNewUsers := s.config.MaxUsersPerThread - users.Len()
// calculate a random number between 1 and maxNewUsers
numNewUsers := RandomIntInRange(1, maxNewUsers)
// create the new users
for i := 0; i < numNewUsers; i++ {
// define a new user
user := &User{
UserID: NextUserId(),
CurrentPage: s.sitemap.RandomLeaf(),
LastChange: time.Now(),
}
// add the user to the list
users.PushBack(user)
// write an event to the topic
err := events.Encode(Event{
Timestamp: unixNow,
UserID: user.UserID,
Path: user.CurrentPage.Path,
// we provide a fake referrer here
Referrer: RandomReferrer(),
})
if err != nil {
return err
}
}
}
// we will be removing elements from the list while we iterate, so we
// need to keep track of next outside of the loop
var next *list.Element
// iterate through the users list and simulate each users behavior
for el := users.Front(); el != nil; el = next {
next = el.Next()
user := el.Value.(*User)
pageTime := time.Since(user.LastChange)
// users only consider leaving a page after at least 5 seconds
if pageTime > time.Second*5 {
// eventProb is a random value from 0 to 1 but is weighted
// to be closer to 0 most of the time
eventProb := math.Pow(rand.Float64(), 2)
if eventProb > 0.98 {
// user has left the site
users.Remove(el)
continue
} else if eventProb > 0.9 {
// user jumps to a random page
user.CurrentPage = s.sitemap.RandomLeaf()
user.LastChange = time.Now()
} else if eventProb > 0.8 {
// user goes to the "next" page
user.CurrentPage = user.CurrentPage.RandomNext()
user.LastChange = time.Now()
}
}
err := events.Encode(Event{
Timestamp: unixNow,
UserID: user.UserID,
Path: user.CurrentPage.Path,
PageTime: pageTime.Seconds(),
})
if err != nil {
return err
}
}
}
return nil
}