From a9866395884b8f2f9121a8bd9763307878a8d494 Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 3 Sep 2019 16:59:47 -0700 Subject: [PATCH] Sentry support --- pyircbot/cli.py | 5 ++++- pyircbot/common.py | 9 +++++++++ pyircbot/irccore.py | 24 ++++++++++++++---------- pyircbot/modules/Error.py | 21 +++++++-------------- pyircbot/pyircbot.py | 2 ++ 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/pyircbot/cli.py b/pyircbot/cli.py index 05be2e8..f802958 100644 --- a/pyircbot/cli.py +++ b/pyircbot/cli.py @@ -3,7 +3,7 @@ import sys import logging import signal from argparse import ArgumentParser -from pyircbot.common import load +from pyircbot.common import load, sentry_sdk from pyircbot import PyIRCBot from json import loads @@ -33,6 +33,9 @@ def main(): botconfig = loads(sys.stdin.read()) if args.config == "-" else load(args.config) + if sentry_sdk and "dsn" in botconfig["bot"]: + sentry_sdk.init(botconfig["bot"]["dsn"]) + log.debug(botconfig) bot = PyIRCBot(botconfig) diff --git a/pyircbot/common.py b/pyircbot/common.py index 58b9318..ad08343 100644 --- a/pyircbot/common.py +++ b/pyircbot/common.py @@ -5,11 +5,20 @@ from collections import namedtuple from time import sleep import os from threading import Thread +try: + import sentry_sdk +except ImportError: + sentry_sdk = None ParsedCommand = namedtuple("ParsedCommand", "command args args_str message") +def report(exception): + if sentry_sdk: + sentry_sdk.capture_exception(exception) + + class burstbucket(object): def __init__(self, maximum, interval): """ diff --git a/pyircbot/irccore.py b/pyircbot/irccore.py index 672618e..d6c21a2 100644 --- a/pyircbot/irccore.py +++ b/pyircbot/irccore.py @@ -12,7 +12,7 @@ import logging import traceback import sys from inspect import getargspec -from pyircbot.common import burstbucket, parse_irc_line +from pyircbot.common import burstbucket, parse_irc_line, report from collections import namedtuple from io import StringIO from time import time @@ -80,9 +80,10 @@ class IRCCore(object): family=self.connection_family, local_addr=self.bind_addr) self.fire_hook("_CONNECT") - except (socket.gaierror, ConnectionRefusedError, OSError): - traceback.print_exc() + except (socket.gaierror, ConnectionRefusedError, OSError) as e: logging.warning("Non-fatal connect error, trying next server...") + self.trace() + report(e) self.server = (self.server + 1) % len(self.servers) await asyncio.sleep(1, loop=loop) continue @@ -97,11 +98,13 @@ class IRCCore(object): .format(command, prefix, args, trailing)) else: self.fire_hook(command, args=args, prefix=prefix, trailing=trailing) - except (ConnectionResetError, asyncio.streams.IncompleteReadError): - traceback.print_exc() + except (ConnectionResetError, asyncio.streams.IncompleteReadError) as e: + self.trace() + report(e) break - except (UnicodeDecodeError, ): - traceback.print_exc() + except (UnicodeDecodeError, ) as e: + self.trace() + report(e) self.fire_hook("_DISCONNECT") self.writer.close() if self.alive: @@ -128,8 +131,8 @@ class IRCCore(object): try: self.writer.write((line + "\r\n").encode("UTF-8")) except Exception as e: # Probably fine if we drop messages while offline - print(e) - print(self.trace()) + self.trace() + report(e) async def kill(self, message="Help! Another thread is killing me :(", forever=True): """Send quit message, flush queue, and close the socket @@ -221,8 +224,9 @@ class IRCCore(object): else: hook(args, prefix, trailing) - except: + except Exception as e: self.log.warning("Error processing hook: \n%s" % self.trace()) + report(e) def addHook(self, command, method): """**Internal.** Enable (connect) a single hook of a module diff --git a/pyircbot/modules/Error.py b/pyircbot/modules/Error.py index 167836e..7c43ba5 100644 --- a/pyircbot/modules/Error.py +++ b/pyircbot/modules/Error.py @@ -7,23 +7,16 @@ """ -from pyircbot.modulebase import ModuleBase, ModuleHook +from pyircbot.modulebase import ModuleBase, hook class Error(ModuleBase): - def __init__(self, bot, moduleName): - ModuleBase.__init__(self, bot, moduleName) - self.hooks = [ModuleHook("PRIVMSG", self.error)] - def error(self, args, prefix, trailing): - """If the message recieved from IRC has the string "error" in it, cause a ZeroDivisionError - - :param args: IRC args received - :type args: list - :param prefix: IRC prefix of sender - :type prefix: str - :param trailing: IRC message body - :type trailing: str""" - if "error" in trailing: + @hook("PRIVMSG") + def error(self, message, command): + """ + If the message recieved from IRC has the string "error" in it, cause a ZeroDivisionError + """ + if "error" in message.trailing: print(10 / 0) diff --git a/pyircbot/pyircbot.py b/pyircbot/pyircbot.py index 05e561f..42562c7 100644 --- a/pyircbot/pyircbot.py +++ b/pyircbot/pyircbot.py @@ -10,6 +10,7 @@ import logging import sys from pyircbot.rpc import BotRPC from pyircbot.irccore import IRCCore +from pyircbot.common import report from socket import AF_INET, AF_INET6 import os.path import asyncio @@ -44,6 +45,7 @@ class ModuleLoader(object): self.log.error("Module %s failed to load: " % name) self.log.error("Module load failure reason: " + str(e)) traceback.print_exc() + report(e) return (False, str(e)) else: self.log.warning("Module %s already imported" % name)