Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use common logger object across entire library #547

Merged
merged 4 commits into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions pottery/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,20 @@

from typing import Tuple

# TODO: When we drop support for Python 3.7, change the following import to:
# from typing import Final
from typing_extensions import Final


__title__ = 'pottery'
__version__ = '2.2.1'
__description__ = __doc__.split(sep='\n\n', maxsplit=1)[0]
__url__ = 'https://github.com/brainix/pottery'
__author__ = 'Rajiv Bakulesh Shah'
__author_email__ = '[email protected]'
__license__ = 'Apache 2.0'
__keywords__ = 'Redis client persistent storage'
__copyright__ = f'Copyright © 2015-2021, {__author__}, original author.'
__title__: Final[str] = 'pottery'
__version__: Final[str] = '2.2.1'
__description__: Final[str] = __doc__.split(sep='\n\n', maxsplit=1)[0]
__url__: Final[str] = 'https://github.com/brainix/pottery'
__author__: Final[str] = 'Rajiv Bakulesh Shah'
__author_email__: Final[str] = '[email protected]'
__license__: Final[str] = 'Apache 2.0'
__keywords__: Final[str] = 'Redis client persistent storage'
__copyright__: Final[str] = f'Copyright © 2015-2021, {__author__}, original author.'


from .exceptions import PotteryError # isort:skip
Expand Down
19 changes: 14 additions & 5 deletions pottery/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,21 @@
from redis import Redis
from redis import RedisError
from redis.client import Pipeline
# TODO: When we drop support for Python 3.7, change the following imports to:
# from typing import Final
# from typing import final
from typing_extensions import Final
from typing_extensions import final

from . import monkey
from .annotations import JSONTypes
from .exceptions import QuorumIsImpossible
from .exceptions import RandomKeyError


logger: Final[logging.Logger] = logging.getLogger('pottery')
_default_url: Final[str] = os.environ.get('REDIS_URL', 'redis://localhost:6379/')
_default_redis: Final[Redis] = Redis.from_url(_default_url, socket_timeout=1)
_logger: Final[logging.Logger] = logging.getLogger('pottery')


def random_key(*,
Expand Down Expand Up @@ -93,7 +97,7 @@ def __init__(self,
def __del__(self) -> None:
if self.key.startswith(self._RANDOM_KEY_PREFIX):
self.redis.delete(self.key)
_logger.warning(
logger.warning(
"Deleted tmp <%s key='%s'> (instance is about to be destroyed)",
self.__class__.__name__,
self.key,
Expand All @@ -117,7 +121,7 @@ def key(self, value: str) -> None:

def _random_key(self) -> str:
key = random_key(redis=self.redis, prefix=self._RANDOM_KEY_PREFIX)
_logger.warning(
logger.warning(
"Self-assigning tmp key <%s key='%s'>",
self.__class__.__name__,
key,
Expand All @@ -133,11 +137,13 @@ def _random_key(self) -> str:
class _Encodable:
'Mixin class that implements JSON encoding and decoding.'

@final
@staticmethod
def _encode(value: JSONTypes) -> str:
encoded = json.dumps(value, sort_keys=True)
return encoded

@final
@staticmethod
def _decode(value: AnyStr) -> JSONTypes:
try:
Expand Down Expand Up @@ -177,6 +183,7 @@ def redis(self) -> Redis:
def key(self) -> str:
'Redis key.'

@final
@contextlib.contextmanager
def __watch_keys(self,
*keys: str,
Expand All @@ -186,19 +193,20 @@ def __watch_keys(self,
try:
yield pipeline
except Exception as error:
_logger.warning(
logger.warning(
'Caught %s; aborting pipeline of %d commands',
error.__class__.__name__,
len(pipeline),
)
raise
else:
_logger.info(
logger.info(
'Running EXEC on pipeline of %d commands',
len(pipeline),
)
pipeline.execute()

@final
def __context_managers(self,
*others: Any,
) -> Generator[ContextManager[Pipeline], None, None]:
Expand All @@ -214,6 +222,7 @@ def __context_managers(self,
pipeline = containers[0].__watch_keys(*keys)
yield pipeline

@final
@contextlib.contextmanager
def _watch(self,
*others: Any,
Expand Down
8 changes: 4 additions & 4 deletions pottery/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import contextlib
import functools
import itertools
import logging
from typing import Any
from typing import Callable
from typing import ClassVar
Expand All @@ -35,10 +34,13 @@

from redis import Redis
from redis.exceptions import WatchError
# TODO: When we drop support for Python 3.7, change the following import to:
# from typing import Final
from typing_extensions import Final

from .base import JSONTypes
from .base import _default_redis
from .base import logger
from .base import random_key
from .dict import InitArg
from .dict import InitIter
Expand All @@ -48,8 +50,6 @@

_DEFAULT_TIMEOUT: Final[int] = 60 # seconds

_logger: Final[logging.Logger] = logging.getLogger('pottery')


class CacheInfo(NamedTuple):
'''Caching decorator information.
Expand Down Expand Up @@ -129,7 +129,7 @@ def decorator(func: F) -> F:
nonlocal redis, key
if key is None: # pragma: no cover
key = random_key(redis=cast(Redis, redis))
_logger.warning(
logger.warning(
"Self-assigning key redis_cache(key='%s') for function %s",
key,
func.__qualname__,
Expand Down
2 changes: 2 additions & 0 deletions pottery/monkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from typing import List
from typing import Union

# TODO: When we drop support for Python 3.7, change the following import to:
# from typing import Final
from typing_extensions import Final


Expand Down
14 changes: 5 additions & 9 deletions pottery/nextid.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import concurrent.futures
import contextlib
import logging
from typing import ClassVar
from typing import Iterable
from typing import List
Expand All @@ -38,17 +37,14 @@
from redis import Redis
from redis import RedisError
from redis.client import Script
from typing_extensions import Final

from .base import Primitive
from .base import logger
from .exceptions import QuorumIsImpossible
from .exceptions import QuorumNotAchieved
from .executor import BailOutExecutor


_logger: Final[logging.Logger] = logging.getLogger('pottery')


class _Scripts:
'''Parent class to define/register Lua scripts for Redis.

Expand Down Expand Up @@ -79,7 +75,7 @@ def __init__(self,
def __register_set_id_script(self) -> None:
if self._set_id_script is None:
class_name = self.__class__.__qualname__
_logger.info('Registering %s._set_id_script', class_name)
logger.info('Registering %s._set_id_script', class_name)
master = next(iter(self.masters)) # type: ignore
self.__class__._set_id_script = master.register_script('''
local curr = tonumber(redis.call('get', KEYS[1]))
Expand Down Expand Up @@ -179,7 +175,7 @@ def __current_id(self) -> int:
current_id = int(cast(bytes, future.result() or b'0'))
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.__current_id() getter caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down Expand Up @@ -215,7 +211,7 @@ def __current_id(self, value: int) -> None:
num_masters_set += future.result() == value
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.__current_id() setter caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down Expand Up @@ -245,7 +241,7 @@ def reset(self) -> None:
future.result()
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.reset() caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down
27 changes: 13 additions & 14 deletions pottery/redlock.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import concurrent.futures
import contextlib
import functools
import logging
import math
import random
import time
Expand All @@ -54,11 +53,14 @@
from redis import Redis
from redis import RedisError
from redis.client import Script
# TODO: When we drop support for Python 3.7, change the following import to:
# from typing import Final
from typing_extensions import Final
from typing_extensions import Literal

from .annotations import F
from .base import Primitive
from .base import logger
from .exceptions import ExtendUnlockedLock
from .exceptions import QuorumNotAchieved
from .exceptions import ReleaseUnlockedLock
Expand All @@ -70,9 +72,6 @@
AUTO_RELEASE_TIME: Final[int] = 10 * 1000


_logger: Final[logging.Logger] = logging.getLogger('pottery')


class _Scripts:
'''Parent class to define/register Lua scripts for Redis.

Expand Down Expand Up @@ -107,7 +106,7 @@ def __init__(self,
def __register_acquired_script(self) -> None:
if self._acquired_script is None:
class_name = self.__class__.__qualname__
_logger.info('Registering %s._acquired_script', class_name)
logger.info('Registering %s._acquired_script', class_name)
master = next(iter(self.masters)) # type: ignore
self.__class__._acquired_script = master.register_script('''
if redis.call('get', KEYS[1]) == ARGV[1] then
Expand All @@ -121,7 +120,7 @@ def __register_acquired_script(self) -> None:
def __register_extend_script(self) -> None:
if self._extend_script is None:
class_name = self.__class__.__qualname__
_logger.info('Registering %s._extend_script', class_name)
logger.info('Registering %s._extend_script', class_name)
master = next(iter(self.masters)) # type: ignore
self.__class__._extend_script = master.register_script('''
if redis.call('get', KEYS[1]) == ARGV[1] then
Expand All @@ -134,7 +133,7 @@ def __register_extend_script(self) -> None:
def __register_release_script(self) -> None:
if self._release_script is None:
class_name = self.__class__.__qualname__
_logger.info('Registering %s._release_script', class_name)
logger.info('Registering %s._release_script', class_name)
master = next(iter(self.masters)) # type: ignore
self.__class__._release_script = master.register_script('''
if redis.call('get', KEYS[1]) == ARGV[1] then
Expand Down Expand Up @@ -319,7 +318,7 @@ def __acquire_masters(self,
num_masters_acquired += future.result()
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.__acquire_masters() caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down Expand Up @@ -396,7 +395,7 @@ def acquire(self,
def log_time_enqueued(timer: ContextTimer, acquired: bool) -> None:
key_suffix = self.key.split(':', maxsplit=1)[1]
time_enqueued = math.ceil(timer.elapsed())
_logger.info(
logger.info(
'source=pottery sample#redlock.enqueued.%s=%dms sample#redlock.acquired.%s=%d',
key_suffix,
time_enqueued,
Expand Down Expand Up @@ -465,7 +464,7 @@ def locked(self, *, raise_on_redis_errors: Optional[bool] = None) -> int:
ttl = future.result()
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.locked() caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down Expand Up @@ -519,7 +518,7 @@ def extend(self, *, raise_on_redis_errors: Optional[bool] = None) -> None:
num_masters_extended += future.result()
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.extend() caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down Expand Up @@ -566,7 +565,7 @@ def release(self, *, raise_on_redis_errors: Optional[bool] = None) -> None:
num_masters_released += future.result()
except RedisError as error:
redis_errors.append(error)
_logger.exception(
logger.exception(
'%s.release() caught %s',
self.__class__.__name__,
error.__class__.__name__,
Expand Down Expand Up @@ -726,7 +725,7 @@ def _log_synchronize(func: F,
holding_timer: ContextTimer,
) -> None:
try:
_logger.info(
logger.info(
'%s() waited for %s for %d ms; held for %d ms',
func.__qualname__,
redlock.key,
Expand All @@ -737,7 +736,7 @@ def _log_synchronize(func: F,
# holding_timer.elapsed() threw a RuntimeError, which means that
# holding_timer never started, which means that we never acquired the
# lock / entered the critical section.
_logger.info(
logger.info(
'%s() waited for %s for %d ms; never acquired lock',
func.__qualname__,
redlock.key,
Expand Down
2 changes: 1 addition & 1 deletion tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
from redis import Redis

from pottery import PotteryWarning
from pottery.base import logger


class TestCase(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
logger = logging.getLogger('pottery')
logger.setLevel(logging.CRITICAL)
warnings.filterwarnings('ignore', category=PotteryWarning)

Expand Down
Loading