Files
mininet/mininet/log.py
T
Bob Lantz 0df8b19568 Renamed logging_mod.py -> log.py
Updated other files accordingly.
2010-02-03 15:38:29 -08:00

132 lines
3.9 KiB
Python

'''Logging functions for Mininet.'''
import logging
from logging import Logger
import types
LEVELS = {'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL}
# change this to logging.INFO to get printouts when running unit tests
LOG_LEVEL_DEFAULT = logging.WARNING
#default: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
LOG_MSG_FORMAT = '%(message)s'
# Modified from python2.5/__init__.py
class StreamHandlerNoNewline(logging.StreamHandler):
'''StreamHandler that doesn't print newlines by default.
Since StreamHandler automatically adds newlines, define a mod to more
easily support interactive mode when we want it, or errors-only logging for
running unit tests.
'''
def emit(self, record):
'''
Emit a record.
If a formatter is specified, it is used to format the record.
The record is then written to the stream with a trailing newline
[N.B. this may be removed depending on feedback]. If exception
information is present, it is formatted using
traceback.print_exception and appended to the stream.
'''
try:
msg = self.format(record)
fs = '%s' # was '%s\n'
if not hasattr(types, 'UnicodeType'): #if no unicode support...
self.stream.write(fs % msg)
else:
try:
self.stream.write(fs % msg)
except UnicodeError:
self.stream.write(fs % msg.encode('UTF-8'))
self.flush()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
class Singleton(type):
'''Singleton pattern from Wikipedia
See http://en.wikipedia.org/wiki/Singleton_pattern#Python
Intended to be used as a __metaclass_ param, as shown for the class below.
Changed cls first args to mcs to satsify pylint.
'''
def __init__(mcs, name, bases, dict_):
super(Singleton, mcs).__init__(name, bases, dict_)
mcs.instance = None
def __call__(mcs, *args, **kw):
if mcs.instance is None:
mcs.instance = super(Singleton, mcs).__call__(*args, **kw)
return mcs.instance
class MininetLogger(Logger, object):
'''Mininet-specific logger
Enable each mininet .py file to with one import:
from mininet.log import lg
...get a default logger that doesn't require one newline per logging call.
Inherit from object to ensure that we have at least one new-style base
class, and can then use the __metaclass__ directive, to prevent this error:
TypeError: Error when calling the metaclass bases
a new-style class can't have only classic bases
If Python2.5/logging/__init__.py defined Filterer as a new-style class,
via Filterer(object): rather than Filterer, we wouldn't need this.
Use singleton pattern to ensure only one logger is ever created.
'''
__metaclass__ = Singleton
def __init__(self):
Logger.__init__(self, "mininet")
# create console handler
ch = StreamHandlerNoNewline()
# create formatter
formatter = logging.Formatter(LOG_MSG_FORMAT)
# add formatter to ch
ch.setFormatter(formatter)
# add ch to lg
self.addHandler(ch)
self.set_loglevel()
def set_loglevel(self, levelname = None):
'''Setup loglevel.
Convenience function to support lowercase names.
@param level_name level name from LEVELS
'''
level = LOG_LEVEL_DEFAULT
if levelname != None:
if levelname not in LEVELS:
raise Exception('unknown loglevel seen in set_loglevel')
else:
level = LEVELS.get(levelname, level)
self.setLevel(level)
self.handlers[0].setLevel(level)
lg = MininetLogger()