github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/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 range listener { 40 logger.Critical("Unable to decode a Kafka packet. Usually, this " + 41 "indicates that the Kafka.Version specified in the orderer " + 42 "configuration is incorrectly set to a version which is newer than " + 43 "the actual Kafka broker version.") 44 } 45 }() 46 } 47 48 // eventLogger adapts a Logger to the sarama.Logger interface. 49 // Additionally, listeners can be registered to be notified when a substring has 50 // been logged. 51 type eventLogger interface { 52 sarama.StdLogger 53 NewListener(substr string) <-chan string 54 RemoveListener(substr string, listener <-chan string) 55 } 56 57 type debugger interface { 58 Debug(...interface{}) 59 } 60 61 type saramaLoggerImpl struct { 62 logger debugger 63 eventListenerSupport *eventListenerSupport 64 } 65 66 func (l saramaLoggerImpl) Print(args ...interface{}) { 67 l.print(fmt.Sprint(args...)) 68 } 69 70 func (l saramaLoggerImpl) Printf(format string, args ...interface{}) { 71 l.print(fmt.Sprintf(format, args...)) 72 } 73 74 func (l saramaLoggerImpl) Println(args ...interface{}) { 75 l.print(fmt.Sprintln(args...)) 76 } 77 78 func (l saramaLoggerImpl) print(message string) { 79 l.eventListenerSupport.fire(message) 80 l.logger.Debug(message) 81 } 82 83 // this should be more than enough for a well behaved listener 84 const listenerChanSize = 100 85 86 func (l saramaLoggerImpl) NewListener(substr string) <-chan string { 87 listener := make(chan string, listenerChanSize) 88 l.eventListenerSupport.addListener(substr, listener) 89 return listener 90 } 91 92 func (l saramaLoggerImpl) RemoveListener(substr string, listener <-chan string) { 93 l.eventListenerSupport.removeListener(substr, listener) 94 } 95 96 // eventListenerSupport maintains a map of substrings to a list of listeners 97 // interested in receiving a notification when the substring is logged. 98 type eventListenerSupport struct { 99 sync.Mutex 100 listeners map[string][]chan string 101 } 102 103 // addListener adds a listener to the list of listeners for the specified substring 104 func (b *eventListenerSupport) addListener(substr string, listener chan string) { 105 b.Lock() 106 defer b.Unlock() 107 if listeners, ok := b.listeners[substr]; ok { 108 b.listeners[substr] = append(listeners, listener) 109 } else { 110 b.listeners[substr] = []chan string{listener} 111 } 112 } 113 114 // fire sends the specified message to each listener that is registered with 115 // a substring contained in the message 116 func (b *eventListenerSupport) fire(message string) { 117 b.Lock() 118 defer b.Unlock() 119 for substr, listeners := range b.listeners { 120 if strings.Contains(message, substr) { 121 for _, listener := range listeners { 122 listener <- message 123 } 124 } 125 } 126 } 127 128 // addListener removes a listener from the list of listeners for the specified substring 129 func (b *eventListenerSupport) removeListener(substr string, listener <-chan string) { 130 b.Lock() 131 defer b.Unlock() 132 if listeners, ok := b.listeners[substr]; ok { 133 for i, l := range listeners { 134 if l == listener { 135 copy(listeners[i:], listeners[i+1:]) 136 listeners[len(listeners)-1] = nil 137 b.listeners[substr] = listeners[:len(listeners)-1] 138 } 139 } 140 } 141 }