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  }