add fallback logger

This commit is contained in:
petrucci4prez 2017-05-22 02:32:19 -04:00
parent 903ec16bb0
commit afb5972567
3 changed files with 60 additions and 40 deletions

View File

@ -18,6 +18,38 @@ class ConfigFile():
with open(self._path, 'w') as f: with open(self._path, 'w') as f:
yaml.dump(self._dict, f, default_flow_style=False) yaml.dump(self._dict, f, default_flow_style=False)
class async:
def __init__(self, daemon=False):
self._daemon = daemon
def __call__(self, f):
def wrapper(*args, **kwargs):
t = Thread(target=f, daemon=self._daemon, args=args, kwargs=kwargs)
t.start()
return wrapper
class CountdownTimer(Thread):
def __init__(self, countdownSeconds, action, sound=None):
self._stopper = Event()
def countdown():
for i in range(countdownSeconds, 0, -1):
if self._stopper.isSet():
return None
if sound and i < countdownSeconds:
sound.play()
time.sleep(1)
action()
super().__init__(target=countdown, daemon=True)
self.start()
def stop(self):
self._stopper.set()
def __del__(self):
self.stop()
def freeBusyPath(path, logger=None): def freeBusyPath(path, logger=None):
# check if any other processes are using file path # check if any other processes are using file path
# if found, politely ask them to exit, else nuke them # if found, politely ask them to exit, else nuke them
@ -50,34 +82,5 @@ def freeBusyPath(path, logger=None):
logger.warning('Failed to terminate PID %s. Sending SIGKILL', p.pid) logger.warning('Failed to terminate PID %s. Sending SIGKILL', p.pid)
p.kill() p.kill()
class async: def fallbackLogger(module, loglevel, msg):
def __init__(self, daemon=False): print('[{}] [{}] Logger not initialized, this will only go to console:\n{}'.format(module, loglevel, msg))
self._daemon = daemon
def __call__(self, f):
def wrapper(*args, **kwargs):
t = Thread(target=f, daemon=self._daemon, args=args, kwargs=kwargs)
t.start()
return wrapper
class CountdownTimer(Thread):
def __init__(self, countdownSeconds, action, sound=None):
self._stopper = Event()
def countdown():
for i in range(countdownSeconds, 0, -1):
if self._stopper.isSet():
return None
if sound and i < countdownSeconds:
sound.play()
time.sleep(1)
action()
super().__init__(target=countdown, daemon=True)
self.start()
def stop(self):
self._stopper.set()
def __del__(self):
self.stop()

23
main.py
View File

@ -5,6 +5,11 @@ import RPi.GPIO as GPIO
from queue import Queue from queue import Queue
from multiprocessing.managers import BaseManager from multiprocessing.managers import BaseManager
from auxilary import fallbackLogger
def printTrace(t):
fallbackLogger(__name__, 'CRITICAL', t)
def clean(): def clean():
GPIO.cleanup() GPIO.cleanup()
@ -12,17 +17,22 @@ def clean():
stateMachine.__del__() stateMachine.__del__()
except NameError: except NameError:
pass pass
# TODO: this part is really wordy and makes me sad
try: try:
logger.info('Terminated root process - PID: %s', os.getpid()) logger.info('Terminated root process - PID: %s', os.getpid())
logger.stop() logger.stop()
except NameError: except NameError:
pass pass
except Exception:
printTrace(traceback.format_exc())
try: try:
manager.__del__() # kill process 2 manager.__del__() # kill process 2
except NameError: except NameError:
pass pass
except Exception:
printTrace(traceback.format_exc())
def sigtermHandler(signum, stackFrame): def sigtermHandler(signum, stackFrame):
logger.info('Caught SIGTERM') logger.info('Caught SIGTERM')
@ -44,7 +54,7 @@ if __name__ == '__main__':
GPIO.setwarnings(False) GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) GPIO.setmode(GPIO.BCM)
manager = ResourceManager() manager = ResourceManager()
manager.start() # Child process 1 manager.start() # Child process 1
@ -58,7 +68,7 @@ if __name__ == '__main__':
from stateMachine import StateMachine from stateMachine import StateMachine
stateMachine = StateMachine() stateMachine = StateMachine()
# TODO: segfaults are annoying :( # TODO: segfaults are annoying :(
#~ signal.signal(signal.SIGSEGV, sig_handler) #~ signal.signal(signal.SIGSEGV, sig_handler)
signal.signal(signal.SIGTERM, sigtermHandler) signal.signal(signal.SIGTERM, sigtermHandler)
@ -67,7 +77,7 @@ if __name__ == '__main__':
time.sleep(31536000) time.sleep(31536000)
except Exception: except Exception:
t = 'Exception caught:\n' + traceback.format_exc() t = traceback.format_exc()
try: try:
criticalError(t) criticalError(t)
@ -77,6 +87,7 @@ if __name__ == '__main__':
try: try:
logger.critical(t) logger.critical(t)
except NameError: except NameError:
print('[__main__] [CRITICAL] Logger not initialized, using print for console output:\n' + t) printTrace(t)
finally:
clean() clean()

View File

@ -1,7 +1,9 @@
import logging, os import logging, os, sys
from subprocess import run, PIPE, CalledProcessError from subprocess import run, PIPE, CalledProcessError
from logging.handlers import TimedRotatingFileHandler, QueueListener, QueueHandler from logging.handlers import TimedRotatingFileHandler, QueueListener, QueueHandler
from auxilary import fallbackLogger
def SlaveLogger(name, level, queue): def SlaveLogger(name, level, queue):
logger = logging.getLogger(name) logger = logging.getLogger(name)
logger.setLevel(getattr(logging, level)) logger.setLevel(getattr(logging, level))
@ -29,8 +31,12 @@ class GlusterFS():
try: try:
run(cmd, check=True, stdout=PIPE, stderr=PIPE) run(cmd, check=True, stdout=PIPE, stderr=PIPE)
except CalledProcessError as e: except CalledProcessError as e:
print(e.stderr.decode('ascii').rstrip()) # we assume that this will only get thrown when the logger is not
# active, so use fallback to get the explicit mount errors
stderr=e.stderr.decode('ascii').rstrip()
fallbackLogger(__name__, 'CRITICAL', stderr)
sys.exit()
class MasterLogger(): class MasterLogger():
def __init__(self, name, level, queue): def __init__(self, name, level, queue):
mountpoint = '/mnt/glusterfs/pyledriver' mountpoint = '/mnt/glusterfs/pyledriver'