forked from Meituan-Dianping/cat-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aggregator_event.go
115 lines (93 loc) · 2.14 KB
/
aggregator_event.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
package cat
import (
"fmt"
"time"
"github.com/Meituan-Dianping/cat-go/message"
)
type eventData struct {
mtype, name string
count, fail int
}
type eventAggregator struct {
scheduleMixin
ch chan *message.Event
dataMap map[string]*eventData
ticker *time.Ticker
}
func (p *eventAggregator) GetName() string {
return "EventAggregator"
}
func (p *eventAggregator) collectAndSend() {
dataMap := p.dataMap
p.dataMap = make(map[string]*eventData)
p.send(dataMap)
}
func (p *eventAggregator) send(dataMap map[string]*eventData) {
if len(dataMap) == 0 {
return
}
t := message.NewTransaction(typeSystem, nameEventAggregator, aggregator.flush)
defer t.Complete()
for _, data := range dataMap {
event := t.NewEvent(data.mtype, data.name)
event.SetData(fmt.Sprintf("%c%d%c%d", batchFlag, data.count, batchSplit, data.fail))
}
}
func (p *eventAggregator) getOrDefault(event *message.Event) *eventData {
key := fmt.Sprintf("%s,%s", event.Type, event.Name)
if data, ok := p.dataMap[key]; ok {
return data
} else {
p.dataMap[key] = &eventData{
mtype: event.Type,
name: event.Name,
count: 0,
fail: 0,
}
return p.dataMap[key]
}
}
func (p *eventAggregator) afterStart() {
p.ticker = time.NewTicker(eventAggregatorInterval)
}
func (p *eventAggregator) beforeStop() {
close(p.ch)
for event := range p.ch {
p.getOrDefault(event).add(event)
}
p.collectAndSend()
p.ticker.Stop()
}
func (p *eventAggregator) process() {
select {
case sig := <-p.signals:
p.handle(sig)
case event := <-p.ch:
p.getOrDefault(event).add(event)
case <-p.ticker.C:
p.collectAndSend()
}
}
func (p *eventAggregator) Put(event *message.Event) {
if !IsEnabled() {
return
}
select {
case p.ch <- event:
default:
logger.Warning("Event aggregator is full")
}
}
func (data *eventData) add(event *message.Event) {
data.count++
if event.GetStatus() != SUCCESS {
data.fail++
}
}
func newEventAggregator() *eventAggregator {
return &eventAggregator{
scheduleMixin: makeScheduleMixedIn(signalEventAggregatorExit),
ch: make(chan *message.Event, eventAggregatorChannelCapacity),
dataMap: make(map[string]*eventData),
}
}