forked from ipfs/kubo
-
Notifications
You must be signed in to change notification settings - Fork 1
/
reqlog.go
129 lines (107 loc) · 2.37 KB
/
reqlog.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
package commands
import (
"strings"
"sync"
"time"
)
// ReqLogEntry is an entry in the request log
type ReqLogEntry struct {
StartTime time.Time
EndTime time.Time
Active bool
Command string
Options map[string]interface{}
Args []string
ID int
log *ReqLog
}
// Copy returns a copy of the ReqLogEntry
func (r *ReqLogEntry) Copy() *ReqLogEntry {
out := *r
out.log = nil
return &out
}
// ReqLog is a log of requests
type ReqLog struct {
Requests []*ReqLogEntry
nextID int
lock sync.Mutex
keep time.Duration
}
// Add creates a ReqLogEntry from a request and adds it to the log
func (rl *ReqLog) Add(req Request) *ReqLogEntry {
rle := &ReqLogEntry{
StartTime: time.Now(),
Active: true,
Command: strings.Join(req.Path(), "/"),
Options: req.Options(),
Args: req.StringArguments(),
ID: rl.nextID,
log: rl,
}
rl.AddEntry(rle)
return rle
}
// AddEntry adds an entry to the log
func (rl *ReqLog) AddEntry(rle *ReqLogEntry) {
rl.lock.Lock()
defer rl.lock.Unlock()
rl.nextID++
rl.Requests = append(rl.Requests, rle)
if rle == nil || !rle.Active {
rl.maybeCleanup()
}
return
}
// ClearInactive removes stale entries
func (rl *ReqLog) ClearInactive() {
rl.lock.Lock()
defer rl.lock.Unlock()
k := rl.keep
rl.keep = 0
rl.cleanup()
rl.keep = k
}
func (rl *ReqLog) maybeCleanup() {
// only do it every so often or it might
// become a perf issue
if len(rl.Requests)%10 == 0 {
rl.cleanup()
}
}
func (rl *ReqLog) cleanup() {
i := 0
now := time.Now()
for j := 0; j < len(rl.Requests); j++ {
rj := rl.Requests[j]
if rj.Active || rl.Requests[j].EndTime.Add(rl.keep).After(now) {
rl.Requests[i] = rl.Requests[j]
i++
}
}
rl.Requests = rl.Requests[:i]
}
// SetKeepTime sets a duration after which an entry will be considered inactive
func (rl *ReqLog) SetKeepTime(t time.Duration) {
rl.lock.Lock()
defer rl.lock.Unlock()
rl.keep = t
}
// Report generates a copy of all the entries in the requestlog
func (rl *ReqLog) Report() []*ReqLogEntry {
rl.lock.Lock()
defer rl.lock.Unlock()
out := make([]*ReqLogEntry, len(rl.Requests))
for i, e := range rl.Requests {
out[i] = e.Copy()
}
return out
}
// Finish marks an entry in the log as finished
func (rl *ReqLog) Finish(rle *ReqLogEntry) {
rl.lock.Lock()
defer rl.lock.Unlock()
rle.Active = false
rle.EndTime = time.Now()
rl.maybeCleanup()
}