-
Notifications
You must be signed in to change notification settings - Fork 9
/
counter.go
163 lines (139 loc) · 2.99 KB
/
counter.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package proc
import (
ntime "github.com/toolkits/time"
"sync"
"time"
)
const (
DefaultOtherMaxSize = 100
DefaultSCounterQpsPeriod = 1
)
// basic counter
type SCounterBase struct {
sync.RWMutex
Name string
Cnt int64
Time string
ts int64
Other map[string]interface{}
}
func NewSCounterBase(name string) *SCounterBase {
uts := time.Now().Unix()
return &SCounterBase{Name: name, Cnt: 0, Time: ntime.FormatTs(uts),
ts: uts, Other: make(map[string]interface{})}
}
func (this *SCounterBase) Get() *SCounterBase {
this.RLock()
defer this.RUnlock()
return &SCounterBase{
Name: this.Name,
Cnt: this.Cnt,
Time: this.Time,
ts: this.ts,
Other: deepCopyMap(this.Other),
}
}
func (this *SCounterBase) SetCnt(cnt int64) {
this.Lock()
this.Cnt = cnt
this.ts = time.Now().Unix()
this.Time = ntime.FormatTs(this.ts)
this.Unlock()
}
func (this *SCounterBase) Incr() {
this.IncrBy(int64(1))
}
func (this *SCounterBase) IncrBy(incr int64) {
this.Lock()
this.Cnt += incr
this.Unlock()
}
func (this *SCounterBase) PutOther(key string, value interface{}) bool {
this.Lock()
defer this.Unlock()
ret := false
_, exist := this.Other[key]
if exist {
this.Other[key] = value
ret = true
} else {
if len(this.Other) < DefaultOtherMaxSize {
this.Other[key] = value
ret = true
}
}
return ret
}
// counter with qps
type SCounterQps struct {
sync.RWMutex
Name string
Cnt int64
Qps int64
Time string
ts int64
lastTs int64
lastCnt int64
Other map[string]interface{}
}
func NewSCounterQps(name string) *SCounterQps {
uts := time.Now().Unix()
return &SCounterQps{Name: name, Cnt: 0, Time: ntime.FormatTs(uts), ts: uts,
Qps: 0, lastCnt: 0, lastTs: uts, Other: make(map[string]interface{})}
}
func (this *SCounterQps) Get() *SCounterQps {
this.Lock()
defer this.Unlock()
this.ts = time.Now().Unix()
this.Time = ntime.FormatTs(this.ts)
// get smooth qps value
if this.ts-this.lastTs > DefaultSCounterQpsPeriod {
this.Qps = int64((this.Cnt - this.lastCnt) / (this.ts - this.lastTs))
this.lastTs = this.ts
this.lastCnt = this.Cnt
}
return &SCounterQps{
Name: this.Name,
Cnt: this.Cnt,
Qps: this.Qps,
Time: this.Time,
ts: this.ts,
lastTs: this.lastTs,
lastCnt: this.lastCnt,
Other: deepCopyMap(this.Other),
}
}
func (this *SCounterQps) Incr() {
this.IncrBy(int64(1))
}
func (this *SCounterQps) IncrBy(incr int64) {
this.Lock()
this.incrBy(incr)
this.Unlock()
}
func (this *SCounterQps) PutOther(key string, value interface{}) bool {
this.Lock()
defer this.Unlock()
ret := false
_, exist := this.Other[key]
if exist {
this.Other[key] = value
ret = true
} else {
if len(this.Other) < DefaultOtherMaxSize {
this.Other[key] = value
ret = true
}
}
return ret
}
func (this *SCounterQps) incrBy(incr int64) {
this.Cnt += incr
}
func deepCopyMap(src map[string]interface{}) map[string]interface{} {
dst := make(map[string]interface{})
for key, val := range src {
dst[key] = val
}
return dst
}