github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/logevents/provider.go (about) 1 package logevents 2 3 import ( 4 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/server" 5 "github.com/fibonacci-chain/fbc/libs/system" 6 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 7 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 8 "github.com/spf13/viper" 9 "sync" 10 "time" 11 ) 12 13 type provider struct { 14 eventChan chan *KafkaMsg 15 identity string 16 logServerUrl string 17 logger log.Logger 18 kafka *logClient 19 subscriberAlive bool 20 21 mutex sync.Mutex 22 lastHeartbeat time.Time 23 } 24 25 func NewProvider(logger log.Logger) log.Subscriber { 26 url := viper.GetString(server.FlagLogServerUrl) 27 if len(url) == 0 { 28 logger.Info("Publishing logs is disabled") 29 return nil 30 } 31 32 p := &provider{ 33 eventChan: make(chan *KafkaMsg, 1000), 34 logServerUrl: url, 35 logger: logger.With("module", "provider"), 36 } 37 p.init() 38 return p 39 } 40 41 func (p *provider) init() { 42 43 var err error 44 p.identity, err = system.GetIpAddr(viper.GetBool(types.FlagAppendPid)) 45 46 if len(p.identity) == 0 { 47 panic("Invalid identity") 48 } 49 50 if err != nil { 51 p.logger.Error("Failed to set identity", "err", err) 52 return 53 } 54 55 role := viper.GetString("consensus-role") 56 if len(role) > 0 { 57 p.identity = role 58 } 59 60 p.kafka = newLogClient(p.logServerUrl, FBCLogTopic, HeartbeatTopic, p.identity) 61 62 p.logger.Info("Provider init", "url", p.logServerUrl, "id", p.identity) 63 64 go p.eventRoutine() 65 go p.expiredRoutine() 66 go p.heartbeatRoutine() 67 } 68 69 func (p *provider) AddEvent(buf log.LogBuf) { 70 if !p.subscriberAlive { 71 return 72 } 73 74 msg := KafkaMsgPool.Get().(*KafkaMsg) 75 msg.Data = buf.String() 76 p.eventChan <- msg 77 } 78 79 func (p *provider) eventRoutine() { 80 for event := range p.eventChan { 81 p.eventHandler(event) 82 } 83 } 84 85 func (p *provider) heartbeatInterval() time.Duration { 86 p.mutex.Lock() 87 defer p.mutex.Unlock() 88 return time.Now().Sub(p.lastHeartbeat) 89 } 90 91 func (p *provider) keepAlive() { 92 p.mutex.Lock() 93 defer p.mutex.Unlock() 94 p.lastHeartbeat = time.Now() 95 p.subscriberAlive = true 96 } 97 98 func (p *provider) expiredRoutine() { 99 ticker := time.NewTicker(ExpiredInterval) 100 for range ticker.C { 101 interval := p.heartbeatInterval() 102 if interval > ExpiredInterval { 103 p.subscriberAlive = false 104 p.logger.Info("Subscriber expired", "not-seen-for", interval) 105 } 106 } 107 } 108 109 func (p *provider) heartbeatRoutine() { 110 for { 111 key, m, err := p.kafka.recv() 112 if err != nil { 113 p.logger.Error("Provider heartbeat routine", "err", err) 114 continue 115 } 116 p.logger.Info("Provider heartbeat routine", 117 "from", key, 118 "value", m.Data, 119 //"topic", m.Topic, 120 "err", err, 121 ) 122 p.keepAlive() 123 } 124 } 125 126 func (p *provider) eventHandler(msg *KafkaMsg) { 127 // DO NOT use p.logger to log anything in this method!!! 128 defer KafkaMsgPool.Put(msg) 129 p.kafka.send(p.identity, msg) 130 }