class ZMQPushLogHandler(logging.Handler): """ Sends logging to ZMQ PUSH socket(s). Log messages have two parts (ZMQ multipart messages): a header and a body. The header is a JSON object with metadata describing the log event. The body is the content of the log message. """ def __init__(self, log_path, zmq_context=None, level=logging.NOTSET): """ log_path The filename that the program would log to if it were using normal file based logging. This may include slashes to indicate directories. Used as a key to identify this log. zmq_context zeromq context. A program should have only one zmq context. If you don't pass a context in, we will create one. level minimum log level. This is usually set externally """ super(ZMQPushLogHandler, self).__init__(level) # if the caller does not suppy a zeromq context (they really should) # we create our own and hold a reference to it so we can terminate it. if zmq_context is None: self._zmq_context = zmq.Context() zmq_context = self._zmq_context else: self._zmq_context = None self._log_line_pusher = LogLinePusher(zmq_context, log_path) def emit(self, record): """ Do whatever it takes to actually log the specified logging record. record python LogRecord object we use only the string returned by record.getMessage() """ formatted_record = self.format(record) self._log_line_pusher.push_log_line(formatted_record) def close(self): """ Tidy up any resources used by the handler. """ super(ZMQPushLogHandler, self).close() self._log_line_pusher.close() if self._zmq_context is not None: self._zmq_context.term()
def main(): """ main entry point """ args = _parse_commandline() zmq_context = zmq.Context() log_line_pusher = LogLinePusher(zmq_context, args.log_path) halt_event = set_signal_handler() while not halt_event.is_set(): try: line = sys.stdin.readline() except IOError: instance = sys.exc_info()[1] if instance.errno == errno.EINTR and halt_event.is_set(): break raise log_line_pusher.push_log_line(line[:-1]) log_line_pusher.close() zmq_context.term() return 0