github.com/confluentinc/confluent-kafka-go@v1.9.2/kafka/log.go (about)

     1  package kafka
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  )
     7  
     8  /*
     9  #include "select_rdkafka.h"
    10  */
    11  import "C"
    12  
    13  // LogEvent represent the log from librdkafka internal log queue
    14  type LogEvent struct {
    15  	Name      string    // Name of client instance
    16  	Tag       string    // Log tag that provides context to the log Message (e.g., "METADATA" or "GRPCOORD")
    17  	Message   string    // Log message
    18  	Level     int       // Log syslog level, lower is more critical.
    19  	Timestamp time.Time // Log timestamp
    20  }
    21  
    22  // newLogEvent creates a new LogEvent from the given rd_kafka_event_t.
    23  //
    24  // This function does not take ownership of the cEvent pointer. You need to
    25  // free its resources using C.rd_kafka_event_destroy afterwards.
    26  //
    27  // The cEvent object needs to be of type C.RD_KAFKA_EVENT_LOG. Calling this
    28  // function with an object of another type has undefined behaviour.
    29  func (h *handle) newLogEvent(cEvent *C.rd_kafka_event_t) LogEvent {
    30  	var tag, message *C.char
    31  	var level C.int
    32  
    33  	C.rd_kafka_event_log(cEvent, &(tag), &(message), &(level))
    34  
    35  	return LogEvent{
    36  		Name:      h.name,
    37  		Tag:       C.GoString(tag),
    38  		Message:   C.GoString(message),
    39  		Level:     int(level),
    40  		Timestamp: time.Now(),
    41  	}
    42  }
    43  
    44  // pollLogEvents polls log events from librdkafka and pushes them to toChannel,
    45  // until doneChan is closed.
    46  //
    47  // Each call to librdkafka times out after timeoutMs. If a call to librdkafka
    48  // is ongoing when doneChan is closed, the function will wait until the call
    49  // returns or times out, whatever happens first.
    50  func (h *handle) pollLogEvents(toChannel chan LogEvent, timeoutMs int, doneChan chan bool) {
    51  	for {
    52  		select {
    53  		case <-doneChan:
    54  			return
    55  
    56  		default:
    57  			cEvent := C.rd_kafka_queue_poll(h.logq, C.int(timeoutMs))
    58  			if cEvent == nil {
    59  				continue
    60  			}
    61  
    62  			if C.rd_kafka_event_type(cEvent) != C.RD_KAFKA_EVENT_LOG {
    63  				C.rd_kafka_event_destroy(cEvent)
    64  				continue
    65  			}
    66  
    67  			logEvent := h.newLogEvent(cEvent)
    68  			C.rd_kafka_event_destroy(cEvent)
    69  
    70  			select {
    71  			case <-doneChan:
    72  				return
    73  
    74  			case toChannel <- logEvent:
    75  				continue
    76  			}
    77  		}
    78  	}
    79  }
    80  
    81  func (logEvent LogEvent) String() string {
    82  	return fmt.Sprintf(
    83  		"[%v][%s][%s][%d]%s",
    84  		logEvent.Timestamp.Format(time.RFC3339),
    85  		logEvent.Name,
    86  		logEvent.Tag,
    87  		logEvent.Level,
    88  		logEvent.Message)
    89  }