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  }