-
Notifications
You must be signed in to change notification settings - Fork 0
/
counter.go
173 lines (147 loc) · 2.89 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
164
165
166
167
168
169
170
171
172
173
package proc
import (
"github.com/fanghongbo/ops-transfer/utils"
"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: utils.UnixTsFormat(uts),
ts: uts, Other: make(map[string]interface{})}
}
func (u *SCounterBase) Get() *SCounterBase {
u.RLock()
defer u.RUnlock()
return &SCounterBase{
Name: u.Name,
Cnt: u.Cnt,
Time: u.Time,
ts: u.ts,
Other: deepCopyMap(u.Other),
}
}
func (u *SCounterBase) SetCnt(cnt int64) {
u.Lock()
u.Cnt = cnt
u.ts = time.Now().Unix()
u.Time = utils.UnixTsFormat(u.ts)
u.Unlock()
}
func (u *SCounterBase) Incr() {
u.IncrBy(int64(1))
}
func (u *SCounterBase) IncrBy(incr int64) {
u.Lock()
u.Cnt += incr
u.Unlock()
}
func (u *SCounterBase) PutOther(key string, value interface{}) bool {
var (
ret bool
exist bool
)
u.Lock()
defer u.Unlock()
ret = false
_, exist = u.Other[key]
if exist {
u.Other[key] = value
ret = true
} else {
if len(u.Other) < DefaultOtherMaxSize {
u.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: utils.UnixTsFormat(uts), ts: uts,
Qps: 0, lastCnt: 0, lastTs: uts, Other: make(map[string]interface{})}
}
func (u *SCounterQps) Get() *SCounterQps {
u.Lock()
defer u.Unlock()
u.ts = time.Now().Unix()
u.Time = utils.UnixTsFormat(u.ts)
// get smooth qps value
if u.ts-u.lastTs > DefaultSCounterQpsPeriod {
u.Qps = int64((u.Cnt - u.lastCnt) / (u.ts - u.lastTs))
u.lastTs = u.ts
u.lastCnt = u.Cnt
}
return &SCounterQps{
Name: u.Name,
Cnt: u.Cnt,
Qps: u.Qps,
Time: u.Time,
ts: u.ts,
lastTs: u.lastTs,
lastCnt: u.lastCnt,
Other: deepCopyMap(u.Other),
}
}
func (u *SCounterQps) Incr() {
u.IncrBy(int64(1))
}
func (u *SCounterQps) IncrBy(incr int64) {
u.Lock()
u.incrBy(incr)
u.Unlock()
}
func (u *SCounterQps) PutOther(key string, value interface{}) bool {
var (
ret bool
exist bool
)
u.Lock()
defer u.Unlock()
ret = false
_, exist = u.Other[key]
if exist {
u.Other[key] = value
ret = true
} else {
if len(u.Other) < DefaultOtherMaxSize {
u.Other[key] = value
ret = true
}
}
return ret
}
func (u *SCounterQps) incrBy(incr int64) {
u.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
}