Skip to content

Commit

Permalink
feat: optimize loggers (#443)
Browse files Browse the repository at this point in the history
* feat: optimize loggers

* fix: unbound local error
  • Loading branch information
BobTheBuidler authored Nov 25, 2024
1 parent e5d0232 commit 301b5b2
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 85 deletions.
46 changes: 27 additions & 19 deletions a_sync/a_sync/abstract.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ is intended for more custom implementations if necessary.
"""

import abc
import logging
from logging import DEBUG, getLogger
from typing import Dict, Any, Tuple

from a_sync._typing import *
Expand All @@ -19,7 +19,7 @@ from a_sync.a_sync._flags cimport validate_and_negate_if_necessary
from a_sync.a_sync._meta import ASyncMeta


logger = logging.getLogger(__name__)
logger = getLogger(__name__)

cdef object c_logger = logger

Expand Down Expand Up @@ -157,27 +157,35 @@ class ASyncABC(metaclass=ASyncMeta):
>>> MyASyncClass.__a_sync_instance_will_be_sync__((), {'sync': True})
True
"""
c_logger.debug(
"checking `%s.%s.__init__` signature against provided kwargs to determine a_sync mode for the new instance",
cls.__module__,
cls.__name__,
)
cdef bint debug_logs
if debug_logs := c_logger.isEnabledFor(DEBUG):
c_logger._log(
DEBUG,
"checking `%s.%s.__init__` signature against provided kwargs to determine a_sync mode for the new instance",
cls.__module__,
cls.__name__,
)

cdef str flag = get_flag_name(kwargs)
cdef bint sync
if flag:
sync = is_sync(flag, kwargs, pop_flag=False) # type: ignore [arg-type]
c_logger.debug(
"kwargs indicate the new instance created with args %s %s is %ssynchronous",
args,
kwargs,
"" if sync else "a",
if not debug_logs:
return is_sync(flag, kwargs, pop_flag=False) if flag else cls.__a_sync_default_mode__() # type: ignore [arg-type]

if not flag:
c_logger._log(
DEBUG,
"No valid flags found in kwargs, checking class definition for defined default"
)
return sync
c_logger.debug(
"No valid flags found in kwargs, checking class definition for defined default"
return cls.__a_sync_default_mode__() # type: ignore [arg-type]

cdef bint sync = is_sync(flag, kwargs, pop_flag=False) # type: ignore [arg-type]
c_logger._log(
DEBUG,
"kwargs indicate the new instance created with args %s %s is %ssynchronous",
args,
kwargs,
"" if sync else "a",
)
return cls.__a_sync_default_mode__() # type: ignore [arg-type]
return sync

####################
# Abstract Methods #
Expand Down
40 changes: 22 additions & 18 deletions a_sync/a_sync/base.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import functools
import inspect
import logging
from contextlib import suppress
from logging import DEBUG, getLogger

from a_sync import exceptions
from a_sync._typing import *
Expand All @@ -10,7 +10,7 @@ from a_sync.a_sync.abstract import ASyncABC
from a_sync.a_sync.flags import VIABLE_FLAGS


logger = logging.getLogger(__name__)
logger = getLogger(__name__)

cdef object c_logger = logger

Expand Down Expand Up @@ -69,18 +69,22 @@ class ASyncGenericBase(ASyncABC):
@functools.cached_property
def __a_sync_flag_name__(self) -> str:
# TODO: cythonize this cache
c_logger.debug("checking a_sync flag for %s", self)
cdef bint debug_logs
if debug_logs := c_logger.isEnabledFor(DEBUG):
c_logger._log(DEBUG, "checking a_sync flag for %s", self)
try:
flag = _get_a_sync_flag_name_from_signature(type(self))
except exceptions.ASyncFlagException:
# We can't get the flag name from the __init__ signature,
# but maybe the implementation sets the flag somewhere else.
# Let's check the instance's atributes
c_logger.debug(
"unable to find flag name using `%s.__init__` signature, checking for flag attributes defined on %s",
self.__class__.__name__,
self,
)
if debug_logs:
c_logger._log(
DEBUG,
"unable to find flag name using `%s.__init__` signature, checking for flag attributes defined on %s",
self.__class__.__name__,
self,
)
present_flags = [flag for flag in VIABLE_FLAGS if hasattr(self, flag)]
if not present_flags:
raise exceptions.NoFlagsFound(self) from None
Expand All @@ -104,7 +108,7 @@ class ASyncGenericBase(ASyncABC):
def __a_sync_default_mode__(cls) -> bint: # type: ignore [override]
cdef object flag
cdef bint flag_value
if not c_logger.isEnabledFor(logging.DEBUG):
if not c_logger.isEnabledFor(DEBUG):
# we can optimize this if we dont need to log `flag` and the return value
try:
flag = _get_a_sync_flag_name_from_signature(cls)
Expand All @@ -126,7 +130,7 @@ class ASyncGenericBase(ASyncABC):

sync = validate_and_negate_if_necessary(flag, flag_value)
c_logger._log(
logging.DEBUG,
DEBUG,
"`%s.%s` indicates default mode is %ssynchronous",
cls,
flag,
Expand All @@ -151,20 +155,20 @@ cdef str _get_a_sync_flag_name_from_class_def(object cls):

cdef bint _a_sync_flag_default_value_from_signature(object cls):
cdef object signature = inspect.signature(cls.__init__)
if not c_logger.isEnabledFor(logging.DEBUG):
if not c_logger.isEnabledFor(DEBUG):
# we can optimize this much better
return signature.parameters[_get_a_sync_flag_name_from_signature(cls)].default

c_logger._log(
logging.DEBUG, "checking `__init__` signature for default %s a_sync flag value", cls
DEBUG, "checking `__init__` signature for default %s a_sync flag value", cls
)
cdef str flag = _get_a_sync_flag_name_from_signature(cls)
cdef object flag_value = signature.parameters[flag].default
if flag_value is inspect._empty: # type: ignore [attr-defined]
raise NotImplementedError(
"The implementation for 'cls' uses an arg to specify sync mode, instead of a kwarg. We are unable to proceed. I suppose we can extend the code to accept positional arg flags if necessary"
)
c_logger._log(logging.DEBUG, "%s defines %s, default value %s", cls, flag, flag_value)
c_logger._log(DEBUG, "%s defines %s, default value %s", cls, flag, flag_value)
return flag_value


Expand All @@ -176,13 +180,13 @@ cdef str _get_a_sync_flag_name_from_signature(object cls):
return None

# if we fail this one there's no need to check again
if not c_logger.isEnabledFor(logging.DEBUG):
if not c_logger.isEnabledFor(DEBUG):
# we can also skip assigning params to a var
return _parse_flag_name_from_list(cls, inspect.signature(cls.__init__).parameters)

c_logger._log(logging.DEBUG, "Searching for flags defined on %s.__init__", cls)
c_logger._log(DEBUG, "Searching for flags defined on %s.__init__", cls)
cdef object parameters = inspect.signature(cls.__init__).parameters
c_logger._log(logging.DEBUG, "parameters: %s", parameters)
c_logger._log(DEBUG, "parameters: %s", parameters)
return _parse_flag_name_from_list(cls, parameters)


Expand All @@ -195,9 +199,9 @@ cdef str _parse_flag_name_from_list(object cls, object items):
if len(present_flags) > 1:
c_logger.debug("There are too many flags defined on %s", cls)
raise exceptions.TooManyFlags(cls, present_flags)
if c_logger.isEnabledFor(logging.DEBUG):
if c_logger.isEnabledFor(DEBUG):
flag = present_flags[0]
c_logger._log(logging.DEBUG, "found flag %s", flag)
c_logger._log(DEBUG, "found flag %s", flag)
return flag
return present_flags[0]

Expand Down
22 changes: 13 additions & 9 deletions a_sync/a_sync/method.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ asynchronously based on various conditions and configurations.
# mypy: disable-error-code=valid-type
# mypy: disable-error-code=misc
import functools
import logging
import weakref
from inspect import isawaitable
from logging import DEBUG, getLogger

from a_sync._typing import *
from a_sync.a_sync._kwargs cimport get_flag_name, is_sync
Expand All @@ -33,7 +33,7 @@ METHOD_CACHE_TTL = 300
cdef int _METHOD_CACHE_TTL = 300


logger = logging.getLogger(__name__)
logger = getLogger(__name__)

cdef object c_logger = logger

Expand Down Expand Up @@ -600,7 +600,9 @@ class ASyncBoundMethod(ASyncFunction[P, T], Generic[I, P, T]):
>>> bound_method(arg1, arg2, kwarg1=value1, sync=True)
"""
cdef object retval, coro
c_logger.debug("calling %s with args: %s kwargs: %s", self, args, kwargs)
cdef bint debug_logs
if debug_logs := c_logger.isEnabledFor(DEBUG):
c_logger._log(DEBUG, "calling %s with args: %s kwargs: %s", self, args, kwargs)
# This could either be a coroutine or a return value from an awaited coroutine,
# depending on if an overriding flag kwarg was passed into the function call.
retval = coro = ASyncFunction.__call__(self, self.__self__, *args, **kwargs)
Expand All @@ -610,13 +612,15 @@ class ASyncBoundMethod(ASyncFunction[P, T], Generic[I, P, T]):
pass
elif _should_await(self, kwargs):
# The awaitable was not awaited, so now we need to check the flag as defined on 'self' and await if appropriate.
c_logger.debug(
"awaiting %s for %s args: %s kwargs: %s", coro, self, args, kwargs
)
if debug_logs:
c_logger._log(
DEBUG, "awaiting %s for %s args: %s kwargs: %s", coro, self, args, kwargs
)
retval = _await(coro)
c_logger.debug(
"returning %s for %s args: %s kwargs: %s", retval, self, args, kwargs
)
if debug_logs:
c_logger._log(
DEBUG, "returning %s for %s args: %s kwargs: %s", retval, self, args, kwargs
)
return retval # type: ignore [call-overload, return-value]
@property
Expand Down
38 changes: 21 additions & 17 deletions a_sync/a_sync/property.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import functools
import logging
from logging import DEBUG, getLogger

import async_property as ap # type: ignore [import]
from typing_extensions import Unpack
Expand All @@ -25,7 +25,7 @@ if TYPE_CHECKING:
from a_sync.task import TaskMapping


logger = logging.getLogger(__name__)
logger = getLogger(__name__)

cdef object c_logger = logger

Expand Down Expand Up @@ -127,26 +127,30 @@ class _ASyncPropertyDescriptorBase(ASyncDescriptor[I, Tuple[()], T]):
)

cdef object retval

cdef bint debug_logs = c_logger.isEnabledFor(DEBUG)
if should_await:
c_logger.debug(
"awaiting awaitable for %s for instance: %s owner: %s",
awaitable,
self,
instance,
owner,
)
if debug_logs:
c_logger._log(
DEBUG,
"awaiting awaitable for %s for instance: %s owner: %s",
awaitable,
self,
instance,
owner,
)
retval = _await(awaitable)
else:
retval = awaitable

c_logger.debug(
"returning %s for %s for instance: %s owner: %s",
retval,
self,
instance,
owner,
)
if debug_logs:
c_logger._log(
DEBUG,
"returning %s for %s for instance: %s owner: %s",
retval,
self,
instance,
owner,
)

return retval

Expand Down
Loading

0 comments on commit 301b5b2

Please sign in to comment.