コード例 #1
0
ファイル: scheduling.py プロジェクト: Kronifer/bot
def _log_task_exception(
        task: asyncio.Task, *,
        suppressed_exceptions: t.Tuple[t.Type[Exception]]) -> None:
    """Retrieve and log the exception raised in `task` if one exists."""
    with contextlib.suppress(asyncio.CancelledError):
        exception = task.exception()
        # Log the exception if one exists.
        if exception and not isinstance(exception, suppressed_exceptions):
            log = get_logger(__name__)
            log.error(f"Error in task {task.get_name()} {id(task)}!",
                      exc_info=exception)
コード例 #2
0
ファイル: base.py プロジェクト: Kronifer/bot
    def assertNotLogs(self, logger=None, level=None, msg=None):  # noqa: N802
        """
        Asserts that no logs of `level` and higher were emitted by `logger`.

        You can specify a specific `logger`, the minimum `logging` level we want to watch and a
        custom `msg` to be added to the `AssertionError` if thrown. If the assertion fails, the
        recorded log records will be outputted with the `AssertionError` message. The context
        manager does not yield a live `look` into the logging records, since we use this context
        manager when we're testing under the assumption that no log records will be emitted.
        """
        if not isinstance(logger, logging.Logger):
            logger = get_logger(logger)

        if level:
            level = logging._nameToLevel.get(level, level)
        else:
            level = logging.INFO

        handler = _CaptureLogHandler()
        old_handlers = logger.handlers[:]
        old_level = logger.level
        old_propagate = logger.propagate

        logger.handlers = [handler]
        logger.setLevel(level)
        logger.propagate = False

        try:
            yield
        except Exception as exc:
            raise exc
        finally:
            logger.handlers = old_handlers
            logger.propagate = old_propagate
            logger.setLevel(old_level)

        if handler.records:
            level_name = logging.getLevelName(level)
            n_logs = len(handler.records)
            base_message = f"{n_logs} logs of {level_name} or higher were triggered on {logger.name}:\n"
            records = [str(record) for record in handler.records]
            record_message = "\n".join(records)
            standard_message = self._truncateMessage(base_message,
                                                     record_message)
            msg = self._formatMessage(msg, standard_message)
            self.fail(msg)
コード例 #3
0
ファイル: _syncers.py プロジェクト: Kronifer/bot
import abc
import typing as t
from collections import namedtuple

from discord import Guild
from discord.ext.commands import Context
from more_itertools import chunked

import bot
from bot.api import ResponseCodeError
from bot.log import get_logger
from bot.utils.members import get_or_fetch_member

log = get_logger(__name__)

CHUNK_SIZE = 1000

# These objects are declared as namedtuples because tuples are hashable,
# something that we make use of when diffing site roles against guild roles.
_Role = namedtuple('Role', ('id', 'name', 'colour', 'permissions', 'position'))
_Diff = namedtuple('Diff', ('created', 'updated', 'deleted'))


# Implementation of static abstract methods are not enforced if the subclass is never instantiated.
# However, methods are kept abstract to at least symbolise that they should be abstract.
class Syncer(abc.ABC):
    """Base class for synchronising the database with objects in the Discord cache."""
    @staticmethod
    @property
    @abc.abstractmethod
    def name() -> str:
コード例 #4
0
ファイル: bot.py プロジェクト: Kronifer/bot
import warnings
from collections import defaultdict
from contextlib import suppress
from typing import Dict, List, Optional

import aiohttp
import discord
from async_rediscache import RedisSession
from discord.ext import commands
from sentry_sdk import push_scope

from bot import api, constants
from bot.async_stats import AsyncStatsClient
from bot.log import get_logger

log = get_logger('bot')
LOCALHOST = "127.0.0.1"


class StartupError(Exception):
    """Exception class for startup errors."""

    def __init__(self, base: Exception):
        super().__init__()
        self.exception = base


class Bot(commands.Bot):
    """A subclass of `discord.ext.commands.Bot` with an aiohttp session and an API client."""

    def __init__(self, *args, redis_session: RedisSession, **kwargs):
コード例 #5
0
ファイル: scheduling.py プロジェクト: Kronifer/bot
    def __init__(self, name: str):
        self.name = name

        self._log = get_logger(f"{__name__}.{name}")
        self._scheduled_tasks: t.Dict[t.Hashable, asyncio.Task] = {}
コード例 #6
0
import aiohttp

import bot
from bot import constants
from bot.bot import Bot, StartupError
from bot.log import get_logger, setup_sentry

setup_sentry()

try:
    bot.instance = Bot.create()
    bot.instance.load_extensions()
    bot.instance.run(constants.Bot.token)
except StartupError as e:
    message = "Unknown Startup Error Occurred."
    if isinstance(e.exception, (aiohttp.ClientConnectorError, aiohttp.ServerDisconnectedError)):
        message = "Could not connect to site API. Is it running?"
    elif isinstance(e.exception, OSError):
        message = "Could not connect to Redis. Is it running?"

    # The exception is logged with an empty message so the actual message is visible at the bottom
    log = get_logger("bot")
    log.fatal("", exc_info=e.exception)
    log.fatal(message)

    exit(69)
コード例 #7
0
 def test_logging_test_case_respects_alternative_logger(self):
     """Test if LoggingTestCase only checks the provided logger."""
     log_one = get_logger("log one")
     log_two = get_logger("log two")
     with LoggingTestCase.assertNotLogs(self, logger=log_one):
         log_two.info("Hello, this should not raise an AssertionError")
コード例 #8
0
 def test_logging_test_case_works_with_logger_instance(self):
     """Test if the LoggingTestCase captures logging for provided logger."""
     log = get_logger("new_logger")
     with self.assertRaises(AssertionError):
         with LoggingTestCase.assertNotLogs(self, logger=log):
             log.info("Hello, this should raise an AssertionError")
コード例 #9
0
 def setUpClass(cls):
     cls.log = get_logger(__name__)
コード例 #10
0
import logging

from bot.log import get_logger

log = get_logger()
log.setLevel(logging.CRITICAL)