From 71d7285c405bd639f1f9f2642ea8fb567b97caec Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 19 Mar 2013 15:05:51 -0400 Subject: Debug improvements: * Added (set|toggle)_core_debug RMI methods to set debugging in the core * Enable plugin debugging when run with -d * Allow enabling debugging on Reporting plugin before threads have started --- src/lib/Bcfg2/Server/Core.py | 71 ++++++++++++++++++++++++++++--- src/lib/Bcfg2/Server/Plugin/base.py | 4 +- src/lib/Bcfg2/Server/Plugins/Reporting.py | 5 ++- 3 files changed, 70 insertions(+), 10 deletions(-) (limited to 'src/lib/Bcfg2/Server') diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py index 72c0953b8..9be71e2e2 100644 --- a/src/lib/Bcfg2/Server/Core.py +++ b/src/lib/Bcfg2/Server/Core.py @@ -99,9 +99,7 @@ class BaseCore(object): #: The Bcfg2 repository directory self.datastore = setup['repo'] - if setup['debug']: - level = logging.DEBUG - elif setup['verbose']: + if setup['verbose']: level = logging.INFO else: level = logging.WARNING @@ -119,6 +117,25 @@ class BaseCore(object): #: A :class:`logging.Logger` object for use by the core self.logger = logging.getLogger('bcfg2-server') + #: Log levels for the various logging handlers with debug True + #: and False. Each loglevel dict is a dict of ``logger name + #: => log level``; the logger names are set in + #: :mod:`Bcfg2.Logger`. The logger name ``default`` is + #: special, and will be used for any log handlers whose name + #: does not appear elsewhere in the dict. At a minimum, + #: ``default`` must be provided. + self._loglevels = {True: dict(default=logging.DEBUG), + False: dict(console=logging.INFO, + default=level)} + + #: Used to keep track of the current debug state of the core. + self.debug_flag = False + + # enable debugging on the core now. debugging is enabled on + # everything else later + if setup['debug']: + self.set_core_debug(None, setup['debug']) + try: filemonitor = \ Bcfg2.Server.FileMonitor.available[setup['filemonitor']] @@ -299,6 +316,11 @@ class BaseCore(object): #: metadata self.metadata_cache = Cache() + if self.debug_flag: + # enable debugging on everything else. + self.plugins[plugin].set_debug(self.debug_flag) + + def plugins_by_type(self, base_cls): """ Return a list of loaded plugins that match the passed type. @@ -731,6 +753,7 @@ class BaseCore(object): self.shutdown() raise + self.set_debug(None, self.debug_flag) self._block() def _daemonize(self): @@ -1141,9 +1164,17 @@ class BaseCore(object): :type address: tuple :returns: bool - The new debug state of the FAM """ - for plugin in self.plugins.values(): - plugin.toggle_debug() - return self.toggle_fam_debug(address) + return self.set_debug(address, not self.debug_flag) + + @exposed + def toggle_core_debug(self, address): + """ Toggle debug status of the server core + + :param address: Client (address, hostname) pair + :type address: tuple + :returns: bool - The new debug state of the FAM + """ + return self.set_core_debug(address, not self.debug_flag) @exposed def toggle_fam_debug(self, _): @@ -1157,6 +1188,8 @@ class BaseCore(object): def set_debug(self, address, debug): """ Explicitly set debug status of the FAM and all plugins + :param address: Client (address, hostname) pair + :type address: tuple :param debug: The new debug status. This can either be a boolean, or a string describing the state (e.g., "true" or "false"; case-insensitive) @@ -1167,7 +1200,31 @@ class BaseCore(object): debug = debug.lower() == "true" for plugin in self.plugins.values(): plugin.set_debug(debug) - return self.set_fam_debug(address, debug) + rv = self.set_core_debug(address, debug) + return self.set_fam_debug(address, debug) and rv + + @exposed + def set_core_debug(self, _, debug): + """ Explicity set debug status of the server core + + :param debug: The new debug status. This can either be a + boolean, or a string describing the state (e.g., + "true" or "false"; case-insensitive) + :type debug: bool or string + :returns: bool - The new debug state of the FAM + """ + if debug not in [True, False]: + debug = debug.lower() == "true" + self.debug_flag = debug + self.logger.info("Core: debug = %s" % debug) + levels = self._loglevels[self.debug_flag] + for handler in logging.root.handlers: + level = levels.get(handler.get_name(), levels['default']) + self.logger.debug("Setting %s log handler to %s" % + (handler.get_name(), + logging.getLevelName(level))) + handler.setLevel(level) + return self.debug_flag @exposed def set_fam_debug(self, _, debug): diff --git a/src/lib/Bcfg2/Server/Plugin/base.py b/src/lib/Bcfg2/Server/Plugin/base.py index 30645e445..f7bc08717 100644 --- a/src/lib/Bcfg2/Server/Plugin/base.py +++ b/src/lib/Bcfg2/Server/Plugin/base.py @@ -34,8 +34,8 @@ class Debuggable(object): :returns: bool - The new value of the debug flag """ self.debug_flag = debug - self.debug_log("%s: debug_flag = %s" % (self.__class__.__name__, - self.debug_flag), + self.debug_log("%s: debug = %s" % (self.__class__.__name__, + self.debug_flag), flag=True) return debug diff --git a/src/lib/Bcfg2/Server/Plugins/Reporting.py b/src/lib/Bcfg2/Server/Plugins/Reporting.py index d072f1a33..a6dc2c1ef 100644 --- a/src/lib/Bcfg2/Server/Plugins/Reporting.py +++ b/src/lib/Bcfg2/Server/Plugins/Reporting.py @@ -65,10 +65,13 @@ class Reporting(Statistics, Threaded, PullSource, Debuggable): (self.name, traceback.format_exc().splitlines()[-1]) self.logger.error(msg) raise PluginInitError(msg) + if self.debug_flag: + self.transport.set_debug(self.debug_flag) def set_debug(self, debug): rv = Debuggable.set_debug(self, debug) - self.transport.set_debug(debug) + if self.transport is not None: + self.transport.set_debug(debug) return rv def process_statistics(self, client, xdata): -- cgit v1.2.3-1-g7c22