github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/catgo/cat-go/cat/aggregator_event.go (about) 1 package cat 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/artisanhe/tools/catgo/cat-go/message" 8 ) 9 10 type eventData struct { 11 mtype, name string 12 13 count, fail int 14 } 15 16 type eventAggregator struct { 17 scheduleMixin 18 ch chan *message.Event 19 dataMap map[string]*eventData 20 ticker *time.Ticker 21 } 22 23 func (p *eventAggregator) GetName() string { 24 return "EventAggregator" 25 } 26 27 func (p *eventAggregator) collectAndSend() { 28 dataMap := p.dataMap 29 p.dataMap = make(map[string]*eventData) 30 p.send(dataMap) 31 } 32 33 func (p *eventAggregator) send(dataMap map[string]*eventData) { 34 35 if len(dataMap) == 0 { 36 return 37 } 38 39 t := message.NewTransaction(typeSystem, nameEventAggregator, aggregator.flush) 40 defer t.Complete() 41 42 for _, data := range dataMap { 43 event := t.NewEvent(data.mtype, data.name) 44 event.SetData(fmt.Sprintf("%c%d%c%d", batchFlag, data.count, batchSplit, data.fail)) 45 } 46 } 47 48 func (p *eventAggregator) getOrDefault(event *message.Event) *eventData { 49 key := fmt.Sprintf("%s,%s", event.Type, event.Name) 50 51 if data, ok := p.dataMap[key]; ok { 52 return data 53 } else { 54 p.dataMap[key] = &eventData{ 55 mtype: event.Type, 56 name: event.Name, 57 count: 0, 58 fail: 0, 59 } 60 return p.dataMap[key] 61 } 62 } 63 64 func (p *eventAggregator) afterStart() { 65 p.ticker = time.NewTicker(eventAggregatorInterval) 66 } 67 68 func (p *eventAggregator) beforeStop() { 69 close(p.ch) 70 71 for event := range p.ch { 72 p.getOrDefault(event).add(event) 73 } 74 p.collectAndSend() 75 76 p.ticker.Stop() 77 } 78 79 func (p *eventAggregator) process() { 80 select { 81 case sig := <-p.signals: 82 p.handle(sig) 83 case event := <-p.ch: 84 p.getOrDefault(event).add(event) 85 case <-p.ticker.C: 86 p.collectAndSend() 87 } 88 } 89 90 func (p *eventAggregator) Put(event *message.Event) { 91 if !IsEnabled() { 92 return 93 } 94 95 select { 96 case p.ch <- event: 97 default: 98 logger.Warning("Event aggregator is full") 99 } 100 } 101 102 func (data *eventData) add(event *message.Event) { 103 data.count++ 104 105 if event.GetStatus() != SUCCESS { 106 data.fail++ 107 } 108 } 109 110 func newEventAggregator() *eventAggregator { 111 return &eventAggregator{ 112 scheduleMixin: makeScheduleMixedIn(signalEventAggregatorExit), 113 ch: make(chan *message.Event, eventAggregatorChannelCapacity), 114 dataMap: make(map[string]*eventData), 115 } 116 }