Example #1
0
    def __init__(self, name_or_logger, fill_rate=None, capacity=None, verbosity=HINT):
        """Set up Logger-like object with some swailing goodness.

        name_or_logger is either a (possibly unicode) string or a
        logging.Logger-like object. If supplied as a string, we simply
        use logging.getLogger.

        fill_rate is the number of tokens per second Logger
        accumulates. Each log output consumes one token.

        capacity is the maximum number of tokens the Logger is allowed
        to have accumulated.

        verbosity is the initial verbosity level (defaults to HINT).
        Setting it to PRIMARY will stop detail and hint outputs.
        Setting it to DETAIL will stop hint outputs. Setting it to
        HINT allows all output.

        """

        if fill_rate and capacity:
            self._tb = TokenBucket(fill_rate, capacity)
        else:
            self._tb = None
        self._tb_lock = threading.Lock()

        if isinstance(name_or_logger, basestring):
            self._logger = logging.getLogger(name_or_logger)
        else:
            self._logger = name_or_logger

        self._verbosity = verbosity
Example #2
0
    def __init__(self,
                 name_or_logger,
                 fill_rate=None,
                 capacity=None,
                 verbosity=HINT,
                 structured_detail=False,
                 with_prefix=True):
        """Set up Logger-like object with some swailing goodness.

        name_or_logger is either a (possibly unicode) string or a
        logging.Logger-like object. If supplied as a string, we simply
        use logging.getLogger.

        fill_rate is the number of tokens per second Logger
        accumulates. Each log output consumes one token.

        capacity is the maximum number of tokens the Logger is allowed
        to have accumulated.

        verbosity is the initial verbosity level (defaults to HINT).
        Setting it to PRIMARY will stop detail and hint outputs.
        Setting it to DETAIL will stop hint outputs. Setting it to
        HINT allows all output.

        When structured_detail is True, logger.detail(msg) expects msg to be a
        dict and json dumps it when logging.

        When with_prefix is True, logger.detail and logger.hint will prefix
        their output with "DETAIL: " and
        "HINT: ", respectively.
        """

        if fill_rate and capacity:
            self._tb = TokenBucket(fill_rate, capacity)
        else:
            self._tb = None
        self._tb_lock = threading.Lock()

        if isinstance(name_or_logger, basestring):
            self._logger = logging.getLogger(name_or_logger)
        else:
            self._logger = name_or_logger

        self._verbosity = verbosity
        self._structured_detail = structured_detail
        self._with_prefix = with_prefix
Example #3
0
    def __init__(self,
                 name_or_logger,
                 fill_rate=None,
                 capacity=None,
                 verbosity=HINT,
                 structured_detail=False,
                 with_prefix=True):
        """Set up Logger-like object with some swailing goodness.

        name_or_logger is either a (possibly unicode) string or a
        logging.Logger-like object. If supplied as a string, we simply
        use logging.getLogger.

        fill_rate is the number of tokens per second Logger
        accumulates. Each log output consumes one token.

        capacity is the maximum number of tokens the Logger is allowed
        to have accumulated.

        verbosity is the initial verbosity level (defaults to HINT).
        Setting it to PRIMARY will stop detail and hint outputs.
        Setting it to DETAIL will stop hint outputs. Setting it to
        HINT allows all output.

        When structured_detail is True, logger.detail(msg) expects msg to be a
        dict and json dumps it when logging.

        When with_prefix is True, logger.detail and logger.hint will prefix
        their output with "DETAIL: " and
        "HINT: ", respectively.
        """

        if fill_rate and capacity:
            self._tb = TokenBucket(fill_rate, capacity)
        else:
            self._tb = None
        self._tb_lock = threading.Lock()

        if isinstance(name_or_logger, basestring):
            self._logger = logging.getLogger(name_or_logger)
        else:
            self._logger = name_or_logger

        self._verbosity = verbosity
        self._structured_detail = structured_detail
        self._with_prefix = with_prefix
Example #4
0
class Logger(object):
    """A logging.Logger-like object with some swailing goodness.

    """

    def __init__(self, name_or_logger, fill_rate=None, capacity=None, verbosity=HINT):
        """Set up Logger-like object with some swailing goodness.

        name_or_logger is either a (possibly unicode) string or a
        logging.Logger-like object. If supplied as a string, we simply
        use logging.getLogger.

        fill_rate is the number of tokens per second Logger
        accumulates. Each log output consumes one token.

        capacity is the maximum number of tokens the Logger is allowed
        to have accumulated.

        verbosity is the initial verbosity level (defaults to HINT).
        Setting it to PRIMARY will stop detail and hint outputs.
        Setting it to DETAIL will stop hint outputs. Setting it to
        HINT allows all output.

        """

        if fill_rate and capacity:
            self._tb = TokenBucket(fill_rate, capacity)
        else:
            self._tb = None
        self._tb_lock = threading.Lock()

        if isinstance(name_or_logger, basestring):
            self._logger = logging.getLogger(name_or_logger)
        else:
            self._logger = name_or_logger

        self._verbosity = verbosity

    def debug(self, msg=None, *args, **kwargs):
        """Write log at DEBUG level. Same arguments as Python's built-in
        Logger.

        """

        return self._log(logging.DEBUG, msg, args, kwargs)

    def info(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at INFO level."""

        return self._log(logging.INFO, msg, args, kwargs)

    def warning(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at WARNING level."""

        return self._log(logging.WARNING, msg, args, kwargs)

    def error(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at ERROR level."""

        return self._log(logging.ERROR, msg, args, kwargs)

    def critical(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at CRITICAL level."""

        return self._log(logging.CRITICAL, msg, args, kwargs)

    def log(self, level, msg=None, *args, **kwargs):
        """Writes log out at any arbitray level."""

        return self._log(level, msg, args, kwargs)

    def set_verbosity(self, level):
        self._verbosity = level


    def _log(self, level, msg, args, kwargs):
        """Throttled log output."""

        with self._tb_lock:
            if self._tb is None:
                throttled = 0
                should_log = True
            else:
                throttled = self._tb.throttle_count
                should_log = self._tb.check_and_consume()

        if should_log:
            if throttled > 0:
                self._logger.log(level, "")
                self._logger.log(
                    level,
                    "(... throttled %d messages ...)",
                    throttled,
                )
                self._logger.log(level, "")

            if msg is not None:
                self._logger.log(level, msg, *args, **kwargs)

            return FancyLogContext(self._logger, level, self._verbosity)
        else:
            return NoopLogContext()
Example #5
0
    def test_throttle(self, clock):
        clock.return_value = 1
        tb = TokenBucket(10, 100)

        # we get to consume 100 tokens...
        for i in xrange(100):
            self.assertTrue(tb.check_and_consume())

        # ...then next one fails
        self.assertFalse(tb.check_and_consume())

        # fill halfway and check level
        clock.return_value += 0.5
        tb._fill()
        self.assertEqual(len(tb), 5)

        clock.return_value += 0.5
        tb._fill()
        self.assertEqual(len(tb), 10)

        # this fill maxes out capacity
        clock.return_value += 10
        tb._fill()
        self.assertEqual(len(tb), 100)

        # attempt to consume more than allowed then check throttle
        # count
        for i in xrange(123):
            tb.check_and_consume()
        self.assertEqual(tb.throttle_count, 23)

        # fill, consume, then check throttle count again
        clock.return_value += 1
        tb.check_and_consume()
        self.assertEqual(tb.throttle_count, 0)
Example #6
0
 def test_simple(self, clock):
     clock.return_value = 1
     tb = TokenBucket(10, 100)
     self.assertEqual(len(tb), 100)
     self.assertTrue(tb.check_and_consume())
Example #7
0
class Logger(object):
    """A logging.Logger-like object with some swailing goodness.

    """
    def __init__(self,
                 name_or_logger,
                 fill_rate=None,
                 capacity=None,
                 verbosity=HINT,
                 structured_detail=False,
                 with_prefix=True):
        """Set up Logger-like object with some swailing goodness.

        name_or_logger is either a (possibly unicode) string or a
        logging.Logger-like object. If supplied as a string, we simply
        use logging.getLogger.

        fill_rate is the number of tokens per second Logger
        accumulates. Each log output consumes one token.

        capacity is the maximum number of tokens the Logger is allowed
        to have accumulated.

        verbosity is the initial verbosity level (defaults to HINT).
        Setting it to PRIMARY will stop detail and hint outputs.
        Setting it to DETAIL will stop hint outputs. Setting it to
        HINT allows all output.

        When structured_detail is True, logger.detail(msg) expects msg to be a
        dict and json dumps it when logging.

        When with_prefix is True, logger.detail and logger.hint will prefix
        their output with "DETAIL: " and
        "HINT: ", respectively.
        """

        if fill_rate and capacity:
            self._tb = TokenBucket(fill_rate, capacity)
        else:
            self._tb = None
        self._tb_lock = threading.Lock()

        if isinstance(name_or_logger, basestring):
            self._logger = logging.getLogger(name_or_logger)
        else:
            self._logger = name_or_logger

        self._verbosity = verbosity
        self._structured_detail = structured_detail
        self._with_prefix = with_prefix

    def debug(self, msg=None, *args, **kwargs):
        """Write log at DEBUG level. Same arguments as Python's built-in
        Logger.

        """

        return self._log(logging.DEBUG, msg, args, kwargs)

    def info(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at INFO level."""

        return self._log(logging.INFO, msg, args, kwargs)

    def warning(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at WARNING level."""

        return self._log(logging.WARNING, msg, args, kwargs)

    def error(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at ERROR level."""

        return self._log(logging.ERROR, msg, args, kwargs)

    def exception(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at ERROR level with exc_info set.

        https://github.com/python/cpython/blob/2.7/Lib/logging/__init__.py#L1472
        """
        kwargs['exc_info'] = 1
        return self._log(logging.ERROR, msg, args, kwargs)

    def critical(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at CRITICAL level."""

        return self._log(logging.CRITICAL, msg, args, kwargs)

    def log(self, level, msg=None, *args, **kwargs):
        """Writes log out at any arbitray level."""

        return self._log(level, msg, args, kwargs)

    def set_verbosity(self, level):
        self._verbosity = level

    def _log(self, level, msg, args, kwargs):
        """Throttled log output."""

        with self._tb_lock:
            if self._tb is None:
                throttled = 0
                should_log = True
            else:
                throttled = self._tb.throttle_count
                should_log = self._tb.check_and_consume()

        if should_log:
            if throttled > 0:
                self._logger.log(level, "")
                self._logger.log(
                    level,
                    "(... throttled %d messages ...)",
                    throttled,
                )
                self._logger.log(level, "")

            if msg is not None:
                self._logger.log(level, msg, *args, **kwargs)

            return FancyLogContext(self._logger, level, self._verbosity,
                                   self._structured_detail, self._with_prefix)
        else:
            return NoopLogContext()
Example #8
0
    def test_throttle(self, clock):
        clock.return_value = 1
        tb = TokenBucket(10, 100)

        # we get to consume 100 tokens...
        for i in xrange(100):
            self.assertTrue(tb.check_and_consume())

        # ...then next one fails
        self.assertFalse(tb.check_and_consume())

        # fill halfway and check level
        clock.return_value += 0.5
        tb._fill()
        self.assertEqual(len(tb), 5)

        clock.return_value += 0.5
        tb._fill()
        self.assertEqual(len(tb), 10)

        # this fill maxes out capacity
        clock.return_value += 10
        tb._fill()
        self.assertEqual(len(tb), 100)

        # attempt to consume more than allowed then check throttle
        # count
        for i in xrange(123):
            tb.check_and_consume()
        self.assertEqual(tb.throttle_count, 23)

        # fill, consume, then check throttle count again
        clock.return_value += 1
        tb.check_and_consume()
        self.assertEqual(tb.throttle_count, 0)
Example #9
0
 def test_simple(self, clock):
     clock.return_value = 1
     tb = TokenBucket(10, 100)
     self.assertEqual(len(tb), 100)
     self.assertTrue(tb.check_and_consume())
Example #10
0
class Logger(object):
    """A logging.Logger-like object with some swailing goodness.

    """

    def __init__(self,
                 name_or_logger,
                 fill_rate=None,
                 capacity=None,
                 verbosity=HINT,
                 structured_detail=False,
                 with_prefix=True):
        """Set up Logger-like object with some swailing goodness.

        name_or_logger is either a (possibly unicode) string or a
        logging.Logger-like object. If supplied as a string, we simply
        use logging.getLogger.

        fill_rate is the number of tokens per second Logger
        accumulates. Each log output consumes one token.

        capacity is the maximum number of tokens the Logger is allowed
        to have accumulated.

        verbosity is the initial verbosity level (defaults to HINT).
        Setting it to PRIMARY will stop detail and hint outputs.
        Setting it to DETAIL will stop hint outputs. Setting it to
        HINT allows all output.

        When structured_detail is True, logger.detail(msg) expects msg to be a
        dict and json dumps it when logging.

        When with_prefix is True, logger.detail and logger.hint will prefix
        their output with "DETAIL: " and
        "HINT: ", respectively.
        """

        if fill_rate and capacity:
            self._tb = TokenBucket(fill_rate, capacity)
        else:
            self._tb = None
        self._tb_lock = threading.Lock()

        if isinstance(name_or_logger, basestring):
            self._logger = logging.getLogger(name_or_logger)
        else:
            self._logger = name_or_logger

        self._verbosity = verbosity
        self._structured_detail = structured_detail
        self._with_prefix = with_prefix

    def debug(self, msg=None, *args, **kwargs):
        """Write log at DEBUG level. Same arguments as Python's built-in
        Logger.

        """

        return self._log(logging.DEBUG, msg, args, kwargs)

    def info(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at INFO level."""

        return self._log(logging.INFO, msg, args, kwargs)

    def warning(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at WARNING level."""

        return self._log(logging.WARNING, msg, args, kwargs)

    def error(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at ERROR level."""

        return self._log(logging.ERROR, msg, args, kwargs)

    def exception(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at ERROR level with exc_info set.

        https://github.com/python/cpython/blob/2.7/Lib/logging/__init__.py#L1472
        """
        kwargs['exc_info'] = 1
        return self._log(logging.ERROR, msg, args, kwargs)

    def critical(self, msg=None, *args, **kwargs):
        """Similar to DEBUG but at CRITICAL level."""

        return self._log(logging.CRITICAL, msg, args, kwargs)

    def log(self, level, msg=None, *args, **kwargs):
        """Writes log out at any arbitray level."""

        return self._log(level, msg, args, kwargs)

    def set_verbosity(self, level):
        self._verbosity = level


    def _log(self, level, msg, args, kwargs):
        """Throttled log output."""

        with self._tb_lock:
            if self._tb is None:
                throttled = 0
                should_log = True
            else:
                throttled = self._tb.throttle_count
                should_log = self._tb.check_and_consume()

        if should_log:
            if throttled > 0:
                self._logger.log(level, "")
                self._logger.log(
                    level,
                    "(... throttled %d messages ...)",
                    throttled,
                )
                self._logger.log(level, "")

            if msg is not None:
                self._logger.log(level, msg, *args, **kwargs)

            return FancyLogContext(self._logger,
                                   level,
                                   self._verbosity,
                                   self._structured_detail,
                                   self._with_prefix)
        else:
            return NoopLogContext()