You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.2 KiB
90 lines
2.2 KiB
3 years ago
|
package kafka
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
/*
|
||
|
#include "select_rdkafka.h"
|
||
|
*/
|
||
|
import "C"
|
||
|
|
||
|
// LogEvent represent the log from librdkafka internal log queue
|
||
|
type LogEvent struct {
|
||
|
Name string // Name of client instance
|
||
|
Tag string // Log tag that provides context to the log Message (e.g., "METADATA" or "GRPCOORD")
|
||
|
Message string // Log message
|
||
|
Level int // Log syslog level, lower is more critical.
|
||
|
Timestamp time.Time // Log timestamp
|
||
|
}
|
||
|
|
||
|
// newLogEvent creates a new LogEvent from the given rd_kafka_event_t.
|
||
|
//
|
||
|
// This function does not take ownership of the cEvent pointer. You need to
|
||
|
// free its resources using C.rd_kafka_event_destroy afterwards.
|
||
|
//
|
||
|
// The cEvent object needs to be of type C.RD_KAFKA_EVENT_LOG. Calling this
|
||
|
// function with an object of another type has undefined behaviour.
|
||
|
func (h *handle) newLogEvent(cEvent *C.rd_kafka_event_t) LogEvent {
|
||
|
var tag, message *C.char
|
||
|
var level C.int
|
||
|
|
||
|
C.rd_kafka_event_log(cEvent, &(tag), &(message), &(level))
|
||
|
|
||
|
return LogEvent{
|
||
|
Name: h.name,
|
||
|
Tag: C.GoString(tag),
|
||
|
Message: C.GoString(message),
|
||
|
Level: int(level),
|
||
|
Timestamp: time.Now(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// pollLogEvents polls log events from librdkafka and pushes them to toChannel,
|
||
|
// until doneChan is closed.
|
||
|
//
|
||
|
// Each call to librdkafka times out after timeoutMs. If a call to librdkafka
|
||
|
// is ongoing when doneChan is closed, the function will wait until the call
|
||
|
// returns or times out, whatever happens first.
|
||
|
func (h *handle) pollLogEvents(toChannel chan LogEvent, timeoutMs int, doneChan chan bool) {
|
||
|
for {
|
||
|
select {
|
||
|
case <-doneChan:
|
||
|
return
|
||
|
|
||
|
default:
|
||
|
cEvent := C.rd_kafka_queue_poll(h.logq, C.int(timeoutMs))
|
||
|
if cEvent == nil {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if C.rd_kafka_event_type(cEvent) != C.RD_KAFKA_EVENT_LOG {
|
||
|
C.rd_kafka_event_destroy(cEvent)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
logEvent := h.newLogEvent(cEvent)
|
||
|
C.rd_kafka_event_destroy(cEvent)
|
||
|
|
||
|
select {
|
||
|
case <-doneChan:
|
||
|
return
|
||
|
|
||
|
case toChannel <- logEvent:
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (logEvent LogEvent) String() string {
|
||
|
return fmt.Sprintf(
|
||
|
"[%v][%s][%s][%d]%s",
|
||
|
logEvent.Timestamp.Format(time.RFC3339),
|
||
|
logEvent.Name,
|
||
|
logEvent.Tag,
|
||
|
logEvent.Level,
|
||
|
logEvent.Message)
|
||
|
}
|