Source code for himbeerecouch.log
import sys
import logging
import traceback
import threading
import multiprocessing
from multiprocessing.util import register_after_fork
import atexit
import Queue
from .util import getmacid
from logging import FileHandler as FH
from logging import StreamHandler as SH
# ============================================================================
# Define Log Handler
# ============================================================================
[docs]class MPLogHandler(logging.Handler):
"""multiprocessing log handler
This handler makes it possible for several processes
to log to the same file by using a queue.
:param out_file: name of output file, if None then is output to stdout/stderr
:type out_file: str
"""
def __init__(self, out_file = None):
logging.Handler.__init__(self)
if out_file is not None:
self._handler = FH(out_file)
else:
self._handler = SH()
self.queue = multiprocessing.Queue(-1)
atexit.register(logging.shutdown)
self._thrd = None
self._is_child = False
# Children will automatically register themselves as chilcren
register_after_fork(self, MPLogHandler.set_is_child)
def set_is_child(self):
self._is_child = True
def start_recv_thread(self):
if self._thrd: return
self._shutdown = False
thrd = threading.Thread(target=self.receive)
thrd.daemon = True
thrd.start()
self._thrd = thrd
def setFormatter(self, fmt):
logging.Handler.setFormatter(self, fmt)
self._handler.setFormatter(fmt)
def receive(self):
while not self._shutdown:
try:
record = self.queue.get(True, 0.3)
self._handler.emit(record)
except (Queue.Empty,IOError):
pass
except (KeyboardInterrupt, SystemExit):
raise
except (EOFError,TypeError):
break
except:
traceback.print_exc(file=sys.stderr)
def shutdown_recv_thread(self):
if self._thrd:
self._shutdown = True
self._thrd.join()
self._thrd = None
def send(self, s):
self.queue.put_nowait(s)
def _format_record(self, record):
if record.args:
record.msg = record.msg % record.args
record.args = None
if record.exc_info:
dummy = self.format(record)
record.exc_info = None
return record
def emit(self, record):
try:
s = self._format_record(record)
# If we are a child, then send the record, otherwise simply emit it
if self._is_child: self.send(s)
else: self._handler.emit(s)
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
def close(self):
self._handler.close()
self.shutdown_recv_thread()
logging.Handler.close(self)
_logger = logging.getLogger()
_logger.setLevel(logging.INFO)
_formatter = logging.Formatter("%(asctime)s [RSPBY/%(processName)s] %(levelname)s %(message)s")
_handler = None
log = _logger.info
# Suppress unnecessary output from requests
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.WARN)
def set_logging_file(out_file=None):
global _handler
if _handler is not None:
_logger.removeHandler(_handler)
_handler = MPLogHandler(out_file)
_handler.setFormatter(_formatter)
_logger.addHandler(_handler)
set_logging_file()
def start_child_logging():
if _handler:
_handler.start_recv_thread()
def stop_child_logging():
if _handler:
_handler.shutdown_recv_thread()