From 0d4655c381a1096920e16ce443ca688a7223755c Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 30 Jan 2016 23:33:03 -0800 Subject: [PATCH] core: support multiple channel loggers with DIFFERENT log levels & fix example conf (#83) --- classes.py | 27 +++++++++++++++++---------- example-conf.yml | 13 ++++++++----- log.py | 15 +++++++++------ plugins/commands.py | 9 +++++---- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/classes.py b/classes.py index e388a9b..b1692b3 100644 --- a/classes.py +++ b/classes.py @@ -37,7 +37,7 @@ class Irc(): (a string), the name of the protocol module to use for this connection, and a configuration object. """ - self.loghandler = None + self.loghandlers = [] self.name = netname.lower() self.conf = conf self.serverdata = conf['servers'][netname] @@ -72,11 +72,19 @@ class Irc(): log.debug('(%s) Setting up channel logging to channels %r', self.name, channels) - if channels and not self.loghandler: - # Only create a handler if we have channels to log to, and one - # doesn't already exist. - self.loghandler = PyLinkChannelLogger(self, channels) - log.addHandler(self.loghandler) + + if not self.loghandlers: + # Only create handlers if they haven't already been set up. + + for channel, chandata in channels.items(): + # Fetch the log level for this channel block. + level = None + if chandata is not None: + level = chandata.get('loglevel') + + handler = PyLinkChannelLogger(self, channel, level=level) + self.loghandlers.append(handler) + log.addHandler(handler) def initVars(self): """ @@ -289,10 +297,9 @@ class Irc(): log.debug('(%s) _disconnect: Setting self.aborted to True.', self.name) self.aborted.set() - if self.loghandler is not None: - log.debug('(%s) Removing channel logging handler due to disconnect.', self.name) - log.removeHandler(self.loghandler) - self.loghandler = None + log.debug('(%s) Removing channel logging handlers due to disconnect.', self.name) + while self.loghandlers: + log.removeHandler(self.loghandlers.pop()) try: log.debug('(%s) _disconnect: Shutting down and closing socket.', self.name) diff --git a/example-conf.yml b/example-conf.yml index 9a0358a..d597d5f 100644 --- a/example-conf.yml +++ b/example-conf.yml @@ -44,11 +44,14 @@ logging: loglevel: INFO inspnet: - - "#services" - - "#pylink-log" + "#services": + loglevel: INFO + "#pylink-notifications" + loglevel: WARNING ts6net: - - "#services" + "#services": + loglevel: INFO files: # Logs to file targets. These will be placed in the log/ folder in the @@ -58,12 +61,12 @@ logging: # When running with ./pylink, this will create log/pylink-errors.log # When running with ./pylink someconf.yml, this will create log/someconf-errors.log - - "errors" + "errors": loglevel: ERROR # Ditto above. When running with ./pylink, it will use log/pylink-commands.log # When running with ./pylink someconf.yml, this will create log/someconf-commands.log - - "commands" + "commands": loglevel: INFO servers: diff --git a/log.py b/log.py index 4517d4e..8be11ef 100644 --- a/log.py +++ b/log.py @@ -57,20 +57,24 @@ class PyLinkChannelLogger(logging.Handler): """ Log handler to log to channels in PyLink. """ - def __init__(self, irc, channels, level=None): + def __init__(self, irc, channel, level=None): super(PyLinkChannelLogger, self).__init__() self.irc = irc - self.channels = channels + self.channel = channel # Use a slightly simpler message formatter - logging to IRC doesn't need # logging the time. formatter = logging.Formatter('[%(levelname)s] %(message)s') self.setFormatter(formatter) + # HACK: Use setLevel twice to first coerse string log levels to ints, + # for easier comparison. + level = level or log.getEffectiveLevel() + self.setLevel(level) + # Log level has to be at least 20 (INFO) to prevent loops due # to outgoing messages being logged - level = level or log.getEffectiveLevel() - loglevel = max(level, 20) + loglevel = max(self.level, 20) self.setLevel(loglevel) def emit(self, record): @@ -80,6 +84,5 @@ class PyLinkChannelLogger(logging.Handler): # Only start logging if we're finished bursting if hasattr(self.irc, 'pseudoclient') and self.irc.connected.is_set(): msg = self.format(record) - for channel in self.channels: - self.irc.msg(channel, msg) + self.irc.msg(self.channel, msg) diff --git a/plugins/commands.py b/plugins/commands.py index c97e356..7e20df9 100644 --- a/plugins/commands.py +++ b/plugins/commands.py @@ -198,10 +198,11 @@ def rehash(irc, source, args): ircobj.serverdata = new_conf['servers'][network] ircobj.botdata = new_conf['bot'] - # Clear the IRC object's channel logger and replace it with a - # new one by re-running logSetup(). - log.removeHandler(ircobj.loghandler) - ircobj.loghandler = None + # Clear the IRC object's channel loggers and replace them with + # new ones by re-running logSetup(). + while ircobj.loghandlers: + log.removeHandler(ircobj.loghandlers.pop()) + ircobj.logSetup() for network, sdata in new_conf['servers'].items():