logger.py
'''\
Logger Classes.
classes:
logger (object)
loglevel (object)
fatal (loglevel)
error (loglevel)
warn (loglevel)
info (loglevel)
verbose (loglevel)
debug (loglevel)
trace (loglevel)
Developer@Sonnack.com
February 2014
'''
from sys import stdout, stderr, argv
from datetime import datetime
class loglevel (object):
'''Log Level class.'''
NameList = ['NOTHING', 'FATAL', 'ERROR', 'WARN', 'INFO', 'VERBOSE', 'DEBUG', 'TRACE', '', 'ALL']
NOTHING = 0
FATAL = 1
ERROR = 2
WARN = 3
INFO = 4
VERBOSE = 5
DEBUG = 6
TRACE = 7
MAGIC = 8
ALL = 9
@classmethod
def getName (cls, level):
if (level < 0) or (loglevel.ALL < level):
raise LookupError("Illegal Logger Level!")
return loglevel.NameList[level]
@classmethod
def getLevel (cls, name):
nm = str(name).strip().upper()
if len(nm) == 0:
return loglevel.NOTHING
if nm in loglist.NameList:
return loglevel.NameList.index(name)
raise LookupError("Illegal Logger Level!")
def __init__ (self, level):
'''Create new Log Level instance.'''
self.level = level
def __repr__ (self):
return self.__class__.__name__
class nothing (loglevel):
'''NOTHING Log Level class.'''
def level (self):
return loglevel.NOTHING
def __init__ (self):
super(self.__class__,self).__init__(loglevel.NOTHING)
def __str__ (self):
return 'NOTHING'
class fatal (loglevel):
'''FATAL Log Level class.'''
def level (self):
return loglevel.FATAL
def __init__ (self):
super(self.__class__,self).__init__(loglevel.FATAL)
def __str__ (self):
return 'FATAL'
class error (loglevel):
'''ERROR Log Level class.'''
def level (self):
return loglevel.ERROR
def __init__ (self):
super(self.__class__,self).__init__(loglevel.ERROR)
def __str__ (self):
return 'ERROR'
class warn (loglevel):
'''WARN Log Level class.'''
def level (self):
return loglevel.WARN
def __init__ (self):
super(self.__class__,self).__init__(loglevel.WARN)
def __str__ (self):
return 'WARN'
class info (loglevel):
'''INFO Log Level class.'''
def level (self):
return loglevel.INFO
def __init__ (self):
super(self.__class__,self).__init__(loglevel.INFO)
def __str__ (self):
return 'INFO'
class verbose (loglevel):
'''VERBOSE Log Level class.'''
def level (self):
return loglevel.VERBOSE
def __init__ (self):
super(self.__class__,self).__init__(loglevel.VERBOSE)
def __str__ (self):
return 'VERBOSE'
class debug (loglevel):
'''DEBUG Log Level class.'''
def level (self):
return loglevel.DEBUG
def __init__ (self):
super(self.__class__,self).__init__(loglevel.DEBUG)
def __str__ (self):
return 'DEBUG'
class trace (loglevel):
'''TRACE Log Level class.'''
def level (self):
return loglevel.TRACE
def __init__ (self):
super(self.__class__,self).__init__(loglevel.TRACE)
def __str__ (self):
return 'TRACE'
class all (loglevel):
'''ALL Log Level class.'''
def level (self):
return loglevel.ALL
def __init__ (self):
super(self.__class__,self).__init__(loglevel.ALL)
def __str__ (self):
return 'ALL'
class _logger (object):
'''Logger singleton class (private).'''
def fatal (self, source, text):
self._write('FATAL', text)
def error (self, source, text):
if loglevel.ERROR <= self.ctrl.level:
self._write('ERROR', source, text)
def warn (self, source, text):
if loglevel.WARN <= self.ctrl.level:
self._write('WARN', source, text)
def info (self, source, text):
if loglevel.INFO <= self.ctrl.level:
self._write('INFO', source, text)
def debug (self, source, text):
if loglevel.DEBUG <= self.ctrl.level:
self._write('DEBUG', source, text)
def trace (self, source, text):
if loglevel.TRACE <= self.ctrl.level:
self._write('TRACE', source, text)
def all (self, source, text):
if loglevel.ALL <= self.ctrl.level:
self._write('ALL', source, text)
def _write (self, mode, source, text):
'''Write log line.'''
if self.fp:
dt = datetime.now()
ts = dt.strftime('%Y-%m-%d %H:%M:%S')
ss = self.patt % (ts, mode, source, text)
self.fp.write(ss)
self.fp.flush()
def newline (self):
'''Write a blank line to the output.'''
if self.fp:
self.fp.write('\n')
self.fp.flush()
def flush (self):
'''Flush output buffer.'''
if self.fp:
self.fp.flush()
def start (self, filename, mode='w'):
'''Start Logging.'''
self.end()
if filename:
self.fp = open(filename, 'w')
self.filename = filename
else:
self.fp = stdout
self.filename = '-'
def end (self):
'''End Logging.'''
if self.fp:
self.fp.flush()
self.fp.close()
self.fp = None
self.filename = '(closed)'
def __init__ (self):
'''Create new Logger Implementation instance.'''
self.patt = '%s [%-5s|%-9s] %s\n'
self.ctrl = trace()
self.fp = None
self.filename = '(new)'
def __del__ (self):
'''Delete Logger Implementation instance.'''
self.end()
class logger (object):
'''Logger singleton class (public).'''
__Impl = None
def level (self, new_level=None):
'''Get (and possibly set a new) Logger Level. (Note: Returns current level, not new one.)'''
old_level = logger.__Impl.ctrl
if new_level:
if not isinstance(new_level,loglevel):
raise TypeError,('New level must be a loglevel object! (Got a %s)' % type(new_level).__name__)
logger.__Impl.ctrl = new_level
return old_level
def fatal (self, s=''): logger.__Impl.fatal(self.name, s)
def error (self, s=''): logger.__Impl.error(self.name, s)
def warn (self, s=''): logger.__Impl.warn (self.name, s)
def info (self, s=''): logger.__Impl.info (self.name, s)
def debug (self, s=''): logger.__Impl.debug(self.name, s)
def trace (self, s=''): logger.__Impl.trace(self.name, s)
def newline (self): logger.__Impl.newline()
def flush (self): logger.__Impl.flush()
def start (self, filename, mode='w'):
logger.__Impl.start(filename, mode=mode)
def end (self):
logger.__Impl.end()
def fp (self):
return logger.__Impl.fp
def __new__ (cls, name):
'''Create a new Logger instance.'''
if not logger.__Impl:
logger.__Impl = _logger()
return super(logger,cls).__new__(cls)
def __init__ (self, name):
'''Create new Logger instance.'''
self.name = name
def __str__ (self):
'''Printable version.'''
s = '%s: %s "%s"'
t = (self.__class__.__name__, self.name, self.patt)
return s % t
def __repr__ (self):
'''JSON-like String.'''
s = '{logger:{name:"%s", patt:"%s"}}'
t = (self.name, self.patt)
return s % t
if __name__ == "__main__":
print 'autorun:',argv[0]
log1 = logger('main')
log1.info("This is a Logger test.")
log2 = logger('sub1')
log2.info("Indications are good for this one!")
log2.start('logger1.log')
log1.debug("I wouldn't get your hopes up.")
log1.warn("(Smart move: switching to dquotes for this!)")
log2.debug("I'm optimistic!!")
log2.warn("(I see what you mean!)")
log3 = logger('another')
log3.error("Can I play, too?")
log2.debug("Oh, look, a new one! Fun!!")
log1.warn("As long as you behave.")
log3.error("I promise to be good!")
log1.end()
log2.end()
log3.debug("Hello? Anyone there??")
log2.debug("Nope! We're closed!!")
log1 = logger('main')
log1.info("But now we're open again.")
log2.debug("So I work again?")
log3.debug("Hooray!!")
log1.warn("Okay, that's enough, we're done.")
log1.start('logger2.log')
log2.debug("Wait!...")
log1.start("logger3.log")
log1.info("What?")
log2.trace("There's more...")
log1.info("Don't want to hear it.")
log1.level(warn())
log3.trace("I have more to say!")
log3.debug("Yoo Hoo!")
log3.info("Is this thing on?")
log3.warn("Danger! Danger, Will Robinson!!")
log1.warn("I'm warning you!")
log3.error("Eek!")
log2.level(info())
log2.info("For your information...")
log3.info("Yay!")
log3.end()
log2.end()
log1.end()
'''eof'''