Skip to content

Support @classmethod in Tracer.capture_method() #2011

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

Closed
1 of 2 tasks
tibbe opened this issue Mar 15, 2023 · 4 comments
Closed
1 of 2 tasks

Support @classmethod in Tracer.capture_method() #2011

tibbe opened this issue Mar 15, 2023 · 4 comments
Labels

Comments

@tibbe
Copy link
Contributor

tibbe commented Mar 15, 2023

Use case

Sometimes you want to trace a @classmethod. In my case I have an ORM-like (https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping) library that provides some get, put, query, etc. class methods in a base class. I want tracing for all subclasses. Something like:

class Table:
    @classmethod
    @tracer.capture_method  # Unclear which should nest innermost.
    def get(cls, id: str):
        db.get(table_name=cls.table_name, id=id)

    table_name: str

class Users:
    table_name = "users"

user = Users.get(123)

This doesn't work at the moment (fails with an error about get not having __module__ defined IIRC, at least if you nest @classmethod innermost).

Solution/User Experience

Either extend capture_method to cover @classmethods or add another decorator.

Ideally, as far as I'm concerned, we actually want to use the actual class (cls) in the sub-segment name. So in the example above "## user_module.Users.get". This provides more information in the span name than using Table. You could extend the same argument to the existing behavior of capture_method for instance methods. Although changing it there would be a breaking change (although probably benign).

Alternative solutions

Currently I've written my own, limited workaround:

_P = ParamSpec('_P')
_R_co = TypeVar('_R_co', covariant=True)


_Class = TypeVar('_Class', bound=type)

# Tracer.capture_method does not work for classmethods, so we need our own
# version.
def decorate_sync_classmethod(
    func: Callable[Concatenate[_Class, _P], _R_co],
) -> Callable[Concatenate[_Class, _P], _R_co]:
    '''Equivalent to `@Tracer.capture_method`, but for classmethods.

    Only works on sync (i.e. not async) classmethods.
    '''
    @functools.wraps(func)
    def wrapper(cls: _Class, *args: _P.args, **kwargs: _P.kwargs) -> _R_co:
        method_name = f'{cls.__module__}.{cls.__qualname__}.{func.__name__}'
        with _tracer.provider.in_subsegment(name=f"## {method_name}"):
            return func(cls, *args, **kwargs)
    return wrapper

Acknowledgment

@tibbe tibbe added feature-request feature request triage Pending triage from maintainers labels Mar 15, 2023
@tibbe
Copy link
Contributor Author

tibbe commented Mar 15, 2023

We're on Python 3.9. Seems like starting with 3.10 __module__ is defined: https://docs.python.org/3/library/functions.html#classmethod. For older Python versions we might have to work around it by digging out the module from cls directly.

@heitorlessa
Copy link
Contributor

heitorlessa commented Mar 16, 2023 via email

@heitorlessa heitorlessa added help wanted Could use a second pair of eyes/hands and removed triage Pending triage from maintainers labels Mar 16, 2023
@sthulb sthulb moved this from Triage to Backlog in Powertools for AWS Lambda (Python) Jun 19, 2023
@anafalcao
Copy link
Contributor

Hey everyone!
Closing this issue as it's been open for a while now, and we didn't have much customer feedback.
Please open a new one if it's still an issue.

@anafalcao anafalcao closed this as not planned Won't fix, can't repro, duplicate, stale Jan 22, 2025
@github-project-automation github-project-automation bot moved this from Backlog to Coming soon in Powertools for AWS Lambda (Python) Jan 22, 2025
Copy link
Contributor

⚠️COMMENT VISIBILITY WARNING⚠️

This issue is now closed. Please be mindful that future comments are hard for our team to see.

If you need more assistance, please either tag a team member or open a new issue that references this one.

If you wish to keep having a conversation with other community members under this issue feel free to do so.

@dreamorosi dreamorosi added rejected and removed help wanted Could use a second pair of eyes/hands labels Jan 22, 2025
@dreamorosi dreamorosi moved this from Coming soon to Closed in Powertools for AWS Lambda (Python) Jan 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

No branches or pull requests

4 participants