import logging from config import get_config, WithLogger class SlackHandler(logging.Handler, WithLogger): """ A logging.Handler subclass for logging messages into a Slack channel. See also: https://docs.python.org/3/library/logging.html#handler-objects """ def __init__(self, slackbot, level): """ `slackbot` is an initialized Slackbot() object `log_channel` is the name of a channel that should receive log messages `level` is the log level to use for logging to the Slack channel """ super(self.__class__, self).__init__(level) # pylint: disable=E1003 self.slackbot = slackbot def emit(self, record): """Do whatever it takes to actually log the specified logging record.""" self.slackbot.say(self.config.log_channel, record.getMessage()) def set_up_slack_logger(slackbot=None): """ Sets up a handler and formatter on a given `logging.Logger` object. * `log_level_env_var` - Grabs logging level from this ENV var. Possible values are standard: "debug", "error", etc. * `log_to_slack_env_var` - Points to an ENV var that indicates whether to log to a Slack channel. * `log_channel` - Indicates the name of the Slack channel to which we'll send logs. * `default_level` - The default log level if one is not set in the environment. * `slackbot` - A slackbot.Slackbot() object ready to send messages to a Slack channel. """ logger = logging.getLogger() if logger.handlers: # We've likely already ran through the rest of this method: return _config = get_config() slack_log_level = getattr(logging, _config.log_level.upper(), logging.INFO) formatter = logging.Formatter('%(asctime)s [%(levelname)s]: %(message)s') logger.setLevel(logging.DEBUG) stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) logger.addHandler(stream_handler) if _config.log_to_channel and _config.log_channel and slackbot: logger.debug("Logging to slack channel: %s", _config.log_channel) slack_handler = SlackHandler(slackbot=slackbot, level=slack_log_level) slack_handler.setFormatter(formatter) logger.addHandler(slack_handler)