Refactor: Tracing with a trace decorator #1620
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
New decorator factory created. This factory makes decorators with a base class key so we can use the decorator in the functions.
this is the old style:
Deep explanation:
We need to call this lines of code before every decorated function:
In this lines there are 3 contextual elements:
traced_feature
: The class or feature that we are tracing and doesn't use to be the same name as the class. In the client there are also an example of 2 different values inside the same class, so we need it customizable.function_name
: The function name that we are tracing. It use to be the name of the function. In the client there are some examples that is not the same and maybe we want to use other name at some point, we can discuss this.request
(.headers
): The request is the first parameter in the actions.Knowing this, I will explain different parts.
The factory
This is a regular factory, the only pourpose of the factory is to provide a common value to all the decorators:
traced_feature
.The decorator
The common form of a decorator in python is something like:
If we want to add arguments we need another wrapping function:
If we want to add OPTIONAL arguments is a bit more complicated. Python will call
decoratorArguments
anyway (with or without arguments), so we need to know what is the case we are covering. So:The examples are from https://realpython.com/primer-on-python-decorators/#creating-decorators-with-optional-arguments that has a very good explanation if you need to read more about decorators.
Our decorator has an optional argument (
traced_function
) that is the name of the function or a custom name. As we can have a function or an string, we create an union type and we will later discriminate the cases. As you can see, the structure is the same.The wrapper
Since we use the
func.__name__
and other decorators may use it, if we return thewrapper
, thefunc.__name__
will bewrapper
and that may cause problems like django autogenerated urls. To avoid that we can use thefunctools.wraps
decorator to copy the metadata of the wrapped function.The args and kwargs are the args of the wrapped function, so we can extract the request from there.