From e89827f2032655a5da441df9e9d26b760828b459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Kochen?= Date: Sun, 11 Apr 2004 23:12:36 +0000 Subject: [PATCH] Added support for logging to a channel. --- scripts/supybot | 1 + src/log.py | 89 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/scripts/supybot b/scripts/supybot index b1297e3e5..2fc7d0ac7 100755 --- a/scripts/supybot +++ b/scripts/supybot @@ -325,6 +325,7 @@ if __name__ == '__main__': conf.strictRfc = options.strictRfc irc = irclib.Irc(nick, user, ident, password) + log._ircHandler._irc = irc # This is nasty callback = Owner.Class() irc.addCallback(callback) driver = drivers.newDriver(server, irc) diff --git a/src/log.py b/src/log.py index 0da907da2..ef515da62 100644 --- a/src/log.py +++ b/src/log.py @@ -43,6 +43,7 @@ import logging import ansi import conf import utils +import ircutils import registry deadlyExceptions = [KeyboardInterrupt, SystemExit] @@ -106,6 +107,28 @@ class BetterFileHandler(logging.FileHandler): self.flush() +class IrcHandler(logging.Handler): + def __init__(self, irc=None): + logging.Handler.__init__(self) + self._irc = irc + + def emit(self, record): + try: + if not self._irc.driver.connected: + return + except AttributeError: + return + if ircutils.isChannel(conf.supybot.log.channel()): + from ircmsgs import privmsg + try: + msg = self.format(record).split('\n') + msg = [line.strip() for line in msg] + msg = ' '.join(msg) + self._irc.queueMsg(privmsg(conf.supybot.log.channel(), msg)) + except: + self.handleError(record) + + class ColorizedFormatter(Formatter): def formatException(self, (E, e, tb)): if conf.supybot.log.stdout.colorized(): @@ -130,6 +153,43 @@ class ColorizedFormatter(Formatter): else: return Formatter.format(self, record, *args, **kwargs) + +class IrcFormatter(Formatter): + def formatException(self, ei): + import cStringIO + import traceback + sio = cStringIO.StringIO() + traceback.print_exception(ei[0], ei[1], None, None, sio) + s = sio.getvalue() + sio.close() + return s + + +class ColorizedIrcFormatter(IrcFormatter): + def formatException(self, (E, e, tb)): + if conf.supybot.log.channel.colorized(): + return ''.join(['\x02\x034', + IrcFormatter.formatException(self, (E, e, tb)), + '\x0F']) + else: + return IrcFormatter.formatException(self, (E, e, tb)) + + def format(self, record, *args, **kwargs): + if conf.supybot.log.channel.colorized(): + color = '' + if record.levelno == logging.CRITICAL: + color = '\x02\x0304' + elif record.levelno == logging.ERROR: + color = '\x0304' + elif record.levelno == logging.WARNING: + color = '\x0307' + return ''.join([color, + IrcFormatter.format(self, record, *args, **kwargs), + '\x0F']) + else: + return IrcFormatter.format(self, record, *args, **kwargs) + + # These are public. formatter = Formatter('%(levelname)s %(asctime)s %(message)s') pluginFormatter = Formatter('%(levelname)s %(asctime)s %(name)s %(message)s') @@ -217,11 +277,16 @@ class MetaFirewall(type): class LogLevel(registry.Value): + def __init__(self, target, default, help, + private=False, showDefault=True, **kwargs): + registry.Value.__init__(self, default, help, private=private, + showDefault=showDefault, **kwargs) + self.target = target def set(self, s): s = s.upper() try: self.value = getattr(logging, s) - _logger.setLevel(self.value) # _logger defined later. + self.target.setLevel(self.value) # _logger defined later. except AttributeError: s = 'Invalid log level: should be one of ' \ 'DEBUG, INFO, WARNING, ERROR, or CRITICAL.' @@ -233,13 +298,16 @@ conf.supybot.directories.register('log', registry.String('logs', """Determines what directory the bot will store its logfiles in.""")) conf.supybot.register('log') -conf.supybot.log.register('level', LogLevel(logging.INFO, +conf.supybot.log.register('level', LogLevel(_logger, logging.INFO, """Determines what the minimum priority level logged will be. Valid values are DEBUG, INFO, WARNING, ERROR, and CRITICAL, in order of increasing priority.""")) conf.supybot.log.register('stdout', registry.Boolean(True, """Determines whether the bot will log to stdout.""")) +conf.supybot.log.register('channel', + registry.String('', """Determines which channel the bot should + log to or empty if none at all.""")) class BooleanRequiredFalseOnWindows(registry.Boolean): def set(self, s): @@ -250,6 +318,9 @@ class BooleanRequiredFalseOnWindows(registry.Boolean): conf.supybot.log.stdout.register('colorized', BooleanRequiredFalseOnWindows(False, """Determines whether the bot's logs to stdout (if enabled) will be colorized with ANSI color.""")) +conf.supybot.log.channel.register('colorized', +BooleanRequiredFalseOnWindows(False, """Determines whether the bot's logs to +irc (if enabled) will be colorized with mIRC colors.""")) conf.supybot.log.register('timestampFormat', registry.String('[%d-%b-%Y %H:%M:%S]', @@ -277,6 +348,20 @@ _stdoutHandler.setFormatter(_stdoutFormatter) _stdoutHandler.setLevel(-1) _logger.addHandler(_stdoutHandler) +conf.supybot.log.stdout.register('level', LogLevel(_stdoutHandler, +logging.DEBUG, """Determines what the minimum priority level logged will be to +stdout. See supybot.log.level for possible values""")) + +_ircHandler = IrcHandler() +_ircFormatter = ColorizedIrcFormatter(_formatString) +_ircHandler.setFormatter(_ircFormatter) +_ircHandler.setLevel(logging.WARNING) +_logger.addHandler(_ircHandler) + +conf.supybot.log.channel.register('level', LogLevel(_ircHandler, +logging.WARNING, """Determines what the minimum priority level logged will be +to IRC. See supybot.log.level for possible values. +(NEVER set this to DEBUG!)""")) # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: