github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/orderer/consensus/kafka/logger.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package kafka 8 9 import ( 10 "fmt" 11 "strings" 12 "sync" 13 14 "github.com/Shopify/sarama" 15 "github.com/hechain20/hechain/common/flogging" 16 "go.uber.org/zap" 17 ) 18 19 var ( 20 logger = flogging.MustGetLogger("orderer.consensus.kafka") 21 saramaLogger eventLogger 22 ) 23 24 // init initializes the samara logger 25 func init() { 26 loggingProvider := flogging.MustGetLogger("orderer.consensus.kafka.sarama") 27 saramaEventLogger := &saramaLoggerImpl{ 28 logger: loggingProvider.WithOptions(zap.AddCallerSkip(3)), 29 eventListenerSupport: &eventListenerSupport{ 30 listeners: make(map[string][]chan string), 31 }, 32 } 33 sarama.Logger = saramaEventLogger 34 saramaLogger = saramaEventLogger 35 } 36 37 // init starts a go routine that detects a possible configuration issue 38 func init() { 39 listener := saramaLogger.NewListener("insufficient data to decode packet") 40 go func() { 41 for range listener { 42 logger.Critical("Unable to decode a Kafka packet. Usually, this " + 43 "indicates that the Kafka.Version specified in the orderer " + 44 "configuration is incorrectly set to a version which is newer than " + 45 "the actual Kafka broker version.") 46 } 47 }() 48 } 49 50 // eventLogger adapts a Logger to the sarama.Logger interface. 51 // Additionally, listeners can be registered to be notified when a substring has 52 // been logged. 53 type eventLogger interface { 54 sarama.StdLogger 55 NewListener(substr string) <-chan string 56 RemoveListener(substr string, listener <-chan string) 57 } 58 59 type debugger interface { 60 Debug(...interface{}) 61 } 62 63 type saramaLoggerImpl struct { 64 logger debugger 65 eventListenerSupport *eventListenerSupport 66 } 67 68 func (l saramaLoggerImpl) Print(args ...interface{}) { 69 l.print(fmt.Sprint(args...)) 70 } 71 72 func (l saramaLoggerImpl) Printf(format string, args ...interface{}) { 73 l.print(fmt.Sprintf(format, args...)) 74 } 75 76 func (l saramaLoggerImpl) Println(args ...interface{}) { 77 l.print(fmt.Sprintln(args...)) 78 } 79 80 func (l saramaLoggerImpl) print(message string) { 81 l.eventListenerSupport.fire(message) 82 l.logger.Debug(message) 83 } 84 85 // this should be more than enough for a well behaved listener 86 const listenerChanSize = 100 87 88 func (l saramaLoggerImpl) NewListener(substr string) <-chan string { 89 listener := make(chan string, listenerChanSize) 90 l.eventListenerSupport.addListener(substr, listener) 91 return listener 92 } 93 94 func (l saramaLoggerImpl) RemoveListener(substr string, listener <-chan string) { 95 l.eventListenerSupport.removeListener(substr, listener) 96 } 97 98 // eventListenerSupport maintains a map of substrings to a list of listeners 99 // interested in receiving a notification when the substring is logged. 100 type eventListenerSupport struct { 101 sync.Mutex 102 listeners map[string][]chan string 103 } 104 105 // addListener adds a listener to the list of listeners for the specified substring 106 func (b *eventListenerSupport) addListener(substr string, listener chan string) { 107 b.Lock() 108 defer b.Unlock() 109 if listeners, ok := b.listeners[substr]; ok { 110 b.listeners[substr] = append(listeners, listener) 111 } else { 112 b.listeners[substr] = []chan string{listener} 113 } 114 } 115 116 // fire sends the specified message to each listener that is registered with 117 // a substring contained in the message 118 func (b *eventListenerSupport) fire(message string) { 119 b.Lock() 120 defer b.Unlock() 121 for substr, listeners := range b.listeners { 122 if strings.Contains(message, substr) { 123 for _, listener := range listeners { 124 listener <- message 125 } 126 } 127 } 128 } 129 130 // addListener removes a listener from the list of listeners for the specified substring 131 func (b *eventListenerSupport) removeListener(substr string, listener <-chan string) { 132 b.Lock() 133 defer b.Unlock() 134 if listeners, ok := b.listeners[substr]; ok { 135 for i, l := range listeners { 136 if l == listener { 137 copy(listeners[i:], listeners[i+1:]) 138 listeners[len(listeners)-1] = nil 139 b.listeners[substr] = listeners[:len(listeners)-1] 140 } 141 } 142 } 143 }