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