From 47ca82397bc395b598c6b68b24cdee9e0d8a76d8 Mon Sep 17 00:00:00 2001 From: Chris Larson Date: Wed, 9 Jun 2010 16:17:29 -0700 Subject: Use the python logging module under the hood for bb.msg Signed-off-by: Chris Larson --- TODO | 20 +++----- bin/bitbake | 7 ++- lib/bb/__init__.py | 10 ++++ lib/bb/event.py | 48 ++++++++++++++++++- lib/bb/msg.py | 130 ++++++++++++++++++++++++++-------------------------- lib/bb/ui/knotty.py | 12 ++--- lib/bb/utils.py | 11 ++--- 7 files changed, 144 insertions(+), 94 deletions(-) diff --git a/TODO b/TODO index 54ee646ff..bf5872a7d 100644 --- a/TODO +++ b/TODO @@ -17,20 +17,12 @@ - Leverage the python logging module - - Create a new logging Handler which instantiates MsgBase derived objects - and passes them along, either via bb.event or directly over the - appropriate queues to the other processes. - - Alter the bb.msg functions to use the logging module. - - Convert bb modules to stop using the bb.msg functions. - - Switch the messaging wrappers in the bb package to use the logging module - directly, as we'll be deprecating the bb.msg versions, but these should - stay around for the metadata to use. - - Deprecate the bb.msg functions. - - Do we want to use the logging module in any of the UIs, for local - messages, as well? If we do, we don't want those to use our handler which - sends the Msg events to the UI :) - Looks like we may be able to use removeHandler.. will have to see how it - interacts with parent/child loggers. +- Convert bb modules to stop using the bb.msg functions. +- Switch the messaging wrappers in the bb package to use the logging module + directly, as we'll be deprecating the bb.msg versions, but these should + stay around for the metadata to use. +- Deprecate the bb.msg functions. +- Should we use the logging module rather than print in the knotty ui? Long term, high impact: diff --git a/bin/bitbake b/bin/bitbake index 116b133c7..06198c45a 100755 --- a/bin/bitbake +++ b/bin/bitbake @@ -23,7 +23,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import os -import sys +import sys, logging sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) @@ -31,6 +31,7 @@ import optparse import warnings from traceback import format_exception import bb +from bb import event import bb.msg from bb import cooker from bb import ui @@ -39,7 +40,7 @@ from bb.server import none #from bb.server import xmlrpc __version__ = "1.11.0" - +logger = logging.getLogger("BitBake") #============================================================================# @@ -159,6 +160,8 @@ Default BBFILES are the .bb files in the current directory.""") configuration = BBConfiguration(options) configuration.pkgs_to_build.extend(args[1:]) + logger.addHandler(event.LogHandler()) + #server = bb.server.xmlrpc server = bb.server.none diff --git a/lib/bb/__init__.py b/lib/bb/__init__.py index 88adfc1df..8cda4255b 100644 --- a/lib/bb/__init__.py +++ b/lib/bb/__init__.py @@ -28,8 +28,18 @@ if sys.version_info < (2, 6, 0): raise RuntimeError("Sorry, python 2.6.0 or later is required for this version of bitbake") import os +import logging import bb.msg +class NullHandler(logging.Handler): + def emit(self, record): + pass + +logging.raiseExceptions = False +logger = logging.getLogger("BitBake") +logger.addHandler(NullHandler()) +logger.setLevel(logging.INFO) + if "BBDEBUG" in os.environ: level = int(os.environ["BBDEBUG"]) if level: diff --git a/lib/bb/event.py b/lib/bb/event.py index 7731649ef..dbcd11e1b 100644 --- a/lib/bb/event.py +++ b/lib/bb/event.py @@ -24,8 +24,9 @@ BitBake build tools. import os, sys import warnings -import bb.utils import pickle +import logging +import bb.utils # This is the pid for which we should generate the event. This is set when # the runqueue forks off. @@ -55,7 +56,7 @@ bb.utils._context["Handled"] = Handled def fire_class_handlers(event, d): import bb.msg - if isinstance(event, bb.msg.MsgBase): + if isinstance(event, MsgBase): return for handler in _handlers: @@ -298,3 +299,46 @@ class DepTreeGenerated(Event): def __init__(self, depgraph): Event.__init__(self) self._depgraph = depgraph + +class MsgBase(Event): + """Base class for messages""" + + def __init__(self, msg): + self._message = msg + Event.__init__(self) + +class MsgDebug(MsgBase): + """Debug Message""" + +class MsgNote(MsgBase): + """Note Message""" + +class MsgWarn(MsgBase): + """Warning Message""" + +class MsgError(MsgBase): + """Error Message""" + +class MsgFatal(MsgBase): + """Fatal Message""" + +class MsgPlain(MsgBase): + """General output""" + +class LogHandler(logging.Handler): + """Dispatch logging messages as bitbake events""" + + messages = ( + (logging.DEBUG, MsgDebug), + (logging.INFO, MsgNote), + (logging.WARNING, MsgWarn), + (logging.ERROR, MsgError), + (logging.CRITICAL, MsgFatal), + ) + + def emit(self, record): + for level, msgclass in self.messages: + if record.levelno <= level: + msg = self.format(record) + fire(msgclass(msg), None) + break diff --git a/lib/bb/msg.py b/lib/bb/msg.py index 8d2bcce45..098b0dc80 100644 --- a/lib/bb/msg.py +++ b/lib/bb/msg.py @@ -23,12 +23,26 @@ Message handling infrastructure for bitbake # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import sys +import logging import collections +from itertools import groupby import bb import bb.event -debug_level = collections.defaultdict(lambda: 0) -verbose = False +class Loggers(dict): + def __getitem__(self, key): + if key in self: + return dict.__getitem__(self, key) + else: + log = logging.getLogger("BitBake.%s" % domain._fields[key]) + dict.__setitem__(self, key, log) + return log + +class DebugLevel(dict): + def __getitem__(self, key): + if key == "default": + key = domain.Default + return get_debug_level(key) def _NamedTuple(name, fields): Tuple = collections.namedtuple(name, " ".join(fields)) @@ -48,94 +62,82 @@ domain = _NamedTuple("Domain", ( "RunQueue", "TaskData", "Util")) +logger = logging.getLogger("BitBake") +loggers = Loggers() +debug_level = DebugLevel() - -class MsgBase(bb.event.Event): - """Base class for messages""" - - def __init__(self, msg): - self._message = msg - bb.event.Event.__init__(self) - -class MsgDebug(MsgBase): - """Debug Message""" - -class MsgNote(MsgBase): - """Note Message""" - -class MsgWarn(MsgBase): - """Warning Message""" - -class MsgError(MsgBase): - """Error Message""" - -class MsgFatal(MsgBase): - """Fatal Message""" - -class MsgPlain(MsgBase): - """General output""" - -# # Message control functions # def set_debug_level(level): - for d in domain: - debug_level[d] = level - debug_level[domain.Default] = level + for log in loggers.itervalues(): + log.setLevel(logging.NOTSET) + + if level: + logger.setLevel(logging.DEBUG - level + 1) + else: + logger.setLevel(logging.INFO) def get_debug_level(msgdomain = domain.Default): - return debug_level[msgdomain] + if not msgdomain: + level = logger.getEffectiveLevel() + else: + level = loggers[msgdomain].getEffectiveLevel() + return max(0, logging.DEBUG - level + 1) def set_verbose(level): - verbose = level - -def set_debug_domains(strdomains): - for domainstr in strdomains: - for d in domain: - if domain._fields[d] == domainstr: - debug_level[d] += 1 + if level: + logger.setLevel(logging.INFO - 1) + else: + logger.setLevel(logging.INFO) + +def set_debug_domains(domainargs): + for (domainarg, iterator) in groupby(domainargs): + for index, msgdomain in enumerate(domain._fields): + if msgdomain == domainarg: + level = len(tuple(iterator)) + if level: + loggers[index].setLevel(logging.DEBUG - level + 1) break else: - warn(None, "Logging domain %s is not valid, ignoring" % domainstr) + warn(None, "Logging domain %s is not valid, ignoring" % domainarg) # # Message handling functions # def debug(level, msgdomain, msg, fn = None): + level = logging.DEBUG - (level - 1) if not msgdomain: - msgdomain = domain.Default + logger.log(level, msg) + else: + loggers[msgdomain].log(level, msg) - if debug_level[msgdomain] >= level: - bb.event.fire(MsgDebug(msg), None) - if not bb.event._ui_handlers: - print('DEBUG: %s' % (msg)) +def plain(msg, fn = None): + logger.log(logging.INFO + 1, msg) def note(level, msgdomain, msg, fn = None): + level = logging.INFO - (level - 1) if not msgdomain: - msgdomain = domain.Default - - if level == 1 or verbose or debug_level[msgdomain] >= 1: - bb.event.fire(MsgNote(msg), None) - if not bb.event._ui_handlers: - print('NOTE: %s' % (msg)) + logger.log(level, msg) + else: + loggers[msgdomain].log(level, msg) def warn(msgdomain, msg, fn = None): - bb.event.fire(MsgWarn(msg), None) - if not bb.event._ui_handlers: - print('WARNING: %s' % (msg)) + if not msgdomain: + logger.warn(msg) + else: + loggers[msgdomain].warn(msg) def error(msgdomain, msg, fn = None): - bb.event.fire(MsgError(msg), None) - print('ERROR: %s' % (msg)) + if not msgdomain: + logger.error(msg) + else: + loggers[msgdomain].error(msg) def fatal(msgdomain, msg, fn = None): - bb.event.fire(MsgFatal(msg), None) - print('FATAL: %s' % (msg)) + if not msgdomain: + logger.critical(msg) + else: + loggers[msgdomain].critical(msg) sys.exit(1) - -def plain(msg, fn = None): - bb.event.fire(MsgPlain(msg), None) - if not bb.event._ui_handlers: - print(msg) diff --git a/lib/bb/ui/knotty.py b/lib/bb/ui/knotty.py index f81759abf..b43a35a13 100644 --- a/lib/bb/ui/knotty.py +++ b/lib/bb/ui/knotty.py @@ -72,23 +72,23 @@ def init(server, eventHandler): print("%s: %s (pid %s)" % (tasknum, activetasks[task]["title"], task)) tasknum = tasknum + 1 - if isinstance(event, bb.msg.MsgPlain): + if isinstance(event, bb.event.MsgPlain): print(event._message) continue - if isinstance(event, bb.msg.MsgDebug): + if isinstance(event, bb.event.MsgDebug): print('DEBUG: ' + event._message) continue - if isinstance(event, bb.msg.MsgNote): + if isinstance(event, bb.event.MsgNote): print('NOTE: ' + event._message) continue - if isinstance(event, bb.msg.MsgWarn): + if isinstance(event, bb.event.MsgWarn): print('WARNING: ' + event._message) continue - if isinstance(event, bb.msg.MsgError): + if isinstance(event, bb.event.MsgError): return_value = 1 print('ERROR: ' + event._message) continue - if isinstance(event, bb.msg.MsgFatal): + if isinstance(event, bb.event.MsgFatal): return_value = 1 print('FATAL: ' + event._message) break diff --git a/lib/bb/utils.py b/lib/bb/utils.py index 199d9fbd0..172c67c23 100644 --- a/lib/bb/utils.py +++ b/lib/bb/utils.py @@ -728,13 +728,12 @@ def init_logger(logger, verbose, debug, debug_domains): Set verbosity and debug levels in the logger """ - if verbose: - logger.set_verbose(True) - if debug: - logger.set_debug_level(debug) + bb.msg.set_debug_level(debug) + elif verbose: + bb.msg.set_verbose(True) else: - logger.set_debug_level(0) + bb.msg.set_debug_level(0) if debug_domains: - logger.set_debug_domains(debug_domains) + bb.msg.set_debug_domains(debug_domains) -- cgit 1.2.3-korg