diff --git a/bot/classes/base_command.py b/bot/classes/base_command.py index f323345..f11f467 100644 --- a/bot/classes/base_command.py +++ b/bot/classes/base_command.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +import logging + class BaseCommand(object): """A base class for commands on IRC. @@ -15,13 +17,15 @@ class BaseCommand(object): def __init__(self, connection): """Constructor for new commands. - + This is called once when the command is loaded (from commands._load_command()). `connection` is a Connection object, allowing us to do self.connection.say(), self.connection.send(), etc, from within a method. """ self.connection = connection + self.logger = logging.getLogger(".".join(("commands", name))) + self.logger.setLevel(logging.DEBUG) def check(self, data): """Returns whether this command should be called in response to 'data'. diff --git a/bot/classes/base_task.py b/bot/classes/base_task.py index 1d57927..281b7be 100644 --- a/bot/classes/base_task.py +++ b/bot/classes/base_task.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +import logging + import config import wiki @@ -16,6 +18,11 @@ class BaseTask(object): """ pass + def _setup_logger(self): + """Set up a basic module-level logger.""" + self.logger = logging.getLogger(".".join(("tasks", name))) + self.logger.setLevel(logging.DEBUG) + def run(self, **kwargs): """Main entry point to run a given task. diff --git a/bot/config.py b/bot/config.py index b657ae2..637615e 100644 --- a/bot/config.py +++ b/bot/config.py @@ -8,7 +8,7 @@ including encrypting and decrypting passwords and making a new config file from scratch at the inital bot run. Usually you'll just want to do "from core import config" and access config data -from within config's five global variables and one function: +from within config's global variables and functions: * config.components - a list of enabled components * config.wiki - a dict of information about wiki-editing @@ -17,7 +17,7 @@ from within config's five global variables and one function: * config.metadata - a dict of miscellaneous information * config.schedule() - returns a list of tasks scheduled to run at a given time -Additionally, functions related to config loading: +Additionally, there are functions used in config loading: * config.load() - loads and parses our config file, returning True if passwords are stored encrypted or False otherwise * config.decrypt() - given a key, decrypts passwords inside our config @@ -25,6 +25,7 @@ Additionally, functions related to config loading: """ import json +import logging from os import path import blowfish @@ -32,10 +33,11 @@ import blowfish script_dir = path.dirname(path.abspath(__file__)) root_dir = path.split(script_dir)[0] config_path = path.join(root_dir, "config.json") +log_dir = path.join(root_dir, "logs") _config = None # Holds data loaded from our config file -# Set our five easy-config-access global variables to None +# Set our easy-config-access global variables to None components, wiki, tasks, irc, metadata = None, None, None, None, None def _load(): @@ -49,6 +51,35 @@ def _load(): print error exit(1) +def _setup_logging(): + """Configures the logging module so it works the way we want it to.""" + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + + if metadata.get("enableLogging"): + import logging.handlers + hand = logging.handlers.TimedRotatingFileHandler + fmt = "[%(asctime)s %(levelname)-8s] %(name)s: %(message)s" + formatter = logging.Formatter(fmt=fmt, datefmt="%Y-%m-%d %H:%M:%S") + + logfile = lambda f: path.join(log_dir, f) + + main_handler = hand(logfile("bot.log"), "midnight", 1. 7) + error_handler = hand(logfile("error.log"), "W", 6, 4) + debug_handler = hand(logfile("debug.log"), "H", 1, 6) + + main_handler.setLevel(logging.INFO) + error_handler.setLevel(logging.ERROR) + debug_handler.setLevel(logging.DEBUG) + + handlers = (main_handler, error_handler, debug_handler) + for h in handlers: + h.setFormatter(formatter) + logger.addHandler(h) + + else: + logger.addHandler(logging.NullHandler()) + def _make_new(): """Make a new config file based on the user's input.""" encrypt = raw_input("Would you like to encrypt passwords stored in config.json? [y/n] ") @@ -94,6 +125,8 @@ def load(): irc = _config.get("irc", {}) metadata = _config.get("metadata", {}) + _setup_logging() + # Are passwords encrypted? return metadata.get("encryptPasswords", False) diff --git a/bot/tasks/__init__.py b/bot/tasks/__init__.py index 64f4f01..402f46a 100644 --- a/bot/tasks/__init__.py +++ b/bot/tasks/__init__.py @@ -39,6 +39,7 @@ def _load_task(filename): return task = sys.modules[name].Task() + task._setup_logger() if not isinstance(task, BaseTask): return