Revision 723d068c mininet/logging_mod.py

View differences:

mininet/logging_mod.py
1 1
'''Logging functions for Mininet.'''
2 2

  
3 3
import logging
4
from logging import Logger
4 5
import types
5 6

  
6 7
LEVELS = {'debug': logging.DEBUG,
......
16 17
LOG_MSG_FORMAT = '%(message)s'
17 18

  
18 19

  
19

  
20 20
# Modified from python2.5/__init__.py
21 21
class StreamHandlerNoNewline(logging.StreamHandler):
22 22
    '''StreamHandler that doesn't print newlines by default.
......
53 53
            self.handleError(record)
54 54

  
55 55

  
56
def set_loglevel(level_name = None):
57
    '''Setup loglevel.
56
class Singleton(type):
57
    '''Singleton pattern from Wikipedia
58

  
59
    See http://en.wikipedia.org/wiki/Singleton_pattern#Python
60

  
61
    Intended to be used as a __metaclass_ param, as shown for the class below.
62

  
63
    Changed cls first args to mcs to satsify pylint.
64
    '''
65

  
66
    def __init__(mcs, name, bases, dict_):
67
        super(Singleton, mcs).__init__(name, bases, dict_)
68
        mcs.instance = None
69

  
70
    def __call__(mcs, *args, **kw):
71
        if mcs.instance is None:
72
            mcs.instance = super(Singleton, mcs).__call__(*args, **kw)
73
            return mcs.instance
74

  
75

  
76
class MininetLogger(Logger, object):
77
    '''Mininet-specific logger
78

  
79
    Enable each mininet .py file to with one import:
80

  
81
       from mininet.logging_mod import lg
82

  
83
    ...get a default logger that doesn't require one newline per logging call.
58 84

  
59
    @param level_name level name from LEVELS
85
    Inherit from object to ensure that we have at least one new-style base
86
    class, and can then use the __metaclass__ directive, to prevent this error:
87

  
88
      TypeError: Error when calling the metaclass bases
89
       a new-style class can't have only classic bases
90

  
91
    If Python2.5/logging/__init__.py defined Filterer as a new-style class,
92
    via Filterer(object): rather than Filterer, we wouldn't need this.
93

  
94
    Use singleton pattern to ensure only one logger is ever created.
60 95
    '''
61
    level = LOG_LEVEL_DEFAULT
62
    if level_name != None:
63
        if level_name not in LEVELS:
64
            raise Exception('unknown loglevel seen in set_loglevel')
65
        else:
66
            level = LEVELS.get(level_name, level)
67

  
68
    lg.setLevel(level)
69
    if len(lg.handlers) != 1:
70
        raise Exception('lg.handlers length not zero in logging_mod')
71
    lg.handlers[0].setLevel(level)
72

  
73

  
74
def _setup_logging():
75
    '''Setup logging for Mininet.'''
76
    global lg
77

  
78
    # create logger if first time
79
    if 'lg' not in globals():
80
        lg = logging.getLogger('mininet')
96
    __metaclass__ = Singleton
97

  
98
    def __init__(self):
99

  
100
        Logger.__init__(self, "mininet")
101

  
81 102
        # create console handler
82 103
        ch = StreamHandlerNoNewline()
83 104
        # create formatter
......
85 106
        # add formatter to ch
86 107
        ch.setFormatter(formatter)
87 108
        # add ch to lg
88
        lg.addHandler(ch)
89
    else:
90
        raise Exception('setup_logging called twice')
109
        self.addHandler(ch)
110

  
111
        self.set_loglevel()
112

  
113
    def set_loglevel(self, levelname = None):
114
        '''Setup loglevel.
115

  
116
        Convenience function to support lowercase names.
117

  
118
        @param level_name level name from LEVELS
119
        '''
120
        level = LOG_LEVEL_DEFAULT
121
        if levelname != None:
122
            if levelname not in LEVELS:
123
                raise Exception('unknown loglevel seen in set_loglevel')
124
            else:
125
                level = LEVELS.get(levelname, level)
91 126

  
92
    set_loglevel()
127
        self.setLevel(level)
128
        self.handlers[0].setLevel(level)
93 129

  
94 130

  
95
# There has to be some better way to ensure we only ever have one logging
96
# variable.  If this check isn't in, the order in which imports occur can
97
# affect whether a program runs, because the variable lg may get rebound.
98
if 'lg' not in globals():
99
    _setup_logging()
131
lg = MininetLogger()

Also available in: Unified diff