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  }