github.com/leverly/deis@v1.0.2/logger/syslog/handler.go (about)

     1  package syslog
     2  
     3  // Handler handles syslog messages
     4  type Handler interface {
     5  	// Handle should return Message (maybe modified) for future processing by
     6  	// other handlers or return nil. If Handle is called with nil message it
     7  	// should complete all remaining work and properly shutdown before return.
     8  	Handle(SyslogMessage) SyslogMessage
     9  }
    10  
    11  // BaseHandler is designed to simplify the creation of real handlers. It
    12  // implements Handler interface using nonblocking queuing of messages and
    13  // simple message filtering.
    14  type BaseHandler struct {
    15  	queue  chan SyslogMessage
    16  	end    chan struct{}
    17  	filter func(SyslogMessage) bool
    18  	ft     bool
    19  }
    20  
    21  // NewBaseHandler creates BaseHandler using a specified filter. If filter is nil
    22  // or if it returns true messages are passed to BaseHandler internal queue
    23  // (of qlen length). If filter returns false or ft is true messages are returned
    24  // to server for future processing by other handlers.
    25  func NewBaseHandler(qlen int, filter func(SyslogMessage) bool, ft bool) *BaseHandler {
    26  	return &BaseHandler{
    27  		queue:  make(chan SyslogMessage, qlen),
    28  		end:    make(chan struct{}),
    29  		filter: filter,
    30  		ft:     ft,
    31  	}
    32  }
    33  
    34  // Handle inserts m in an internal queue. It immediately returns even if
    35  // queue is full. If m == nil it closes queue and waits for End method call
    36  // before return.
    37  func (h *BaseHandler) Handle(m SyslogMessage) SyslogMessage {
    38  	if m == nil {
    39  		close(h.queue) // signal that there is no more messages for processing
    40  		<-h.end        // wait for handler shutdown
    41  		return nil
    42  	}
    43  	if h.filter != nil && !h.filter(m) {
    44  		// m doesn't match the filter
    45  		return m
    46  	}
    47  	// Try queue m
    48  	select {
    49  	case h.queue <- m:
    50  	default:
    51  	}
    52  	if h.ft {
    53  		return m
    54  	}
    55  	return nil
    56  }
    57  
    58  // Get returns first message from internal queue. It waits for message if queue
    59  // is empty. It returns nil if there is no more messages to process and handler
    60  // should shutdown.
    61  func (h *BaseHandler) Get() SyslogMessage {
    62  	m, ok := <-h.queue
    63  	if ok {
    64  		return m
    65  	}
    66  	return nil
    67  }
    68  
    69  // Queue returns the BaseHandler internal queue as a read-only channel. You can use
    70  // it directly, especially if your handler needs to select from multiple channels
    71  // or have to work without blocking. You need to check if this channel is closed by
    72  // sender and properly shutdown in this case.
    73  func (h *BaseHandler) Queue() <-chan SyslogMessage {
    74  	return h.queue
    75  }
    76  
    77  // End signals the server that the handler properly shutdown. You need to call End
    78  // only if Get has returned nil before.
    79  func (h *BaseHandler) End() {
    80  	close(h.end)
    81  }