Skip to content

Split logging features of fastapi_log #8

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

Open
wants to merge 72 commits into
base: 16.0-add-fastapi_log
Choose a base branch
from

Conversation

SirPyTech
Copy link

@SirPyTech SirPyTech commented Apr 23, 2025

As suggested in

Thanks for working on this. I wanted to do it since a while 😅

Early feedback...

The way I was planning to handle this was to have a base module to collect any kind of "request/response log".
This can be used by fastapi, base_rest, edi framework, endpoints and any custom implementation of request/response feature.

Would you consider splitting this part to a module like request_log or something like that?

Originally posted by @simahawk in OCA#501 (comment)

Also add the module fastapi_log_mail to optionally send an email when an exception occurs.

Depends on:

lmignon and others added 20 commits January 8, 2025 11:58
Each time a fastapi app is created, a new event loop thread is created by the ASGIMiddleware. Unfortunately, every time the cache is cleared, a new app is created with a new even loop thread. This leads to an increase in the number of threads created to manage the asyncio event loop, even though many of them are no longer in use. To avoid this problem, the thread in charge of the event loop is now created only once per thread / process and the result is stored in the thread's local storage. If a new instance of an app needs to be created following a cache reset, this ensures that the same event loop is reused.

refs OCA#484
This commit adds event loop lifecycle management to the FastAPI dispatcher.

Before this commit, an event loop and the thread to run it were created
each time a FastAPI app was created. The drawback of this approach is that
when the app was destroyed (for example, when the cache of app was cleared),
the event loop and the thread were not properly stopped, which could lead
to memory leaks and zombie threads. This commit fixes this issue by creating
a pool of event loops and threads that are shared among all FastAPI apps.
On each call to a FastAPI app, a event loop is requested from the pool and
is returned to the pool when the app is destroyed. At request time of
an event loop, the pool try to reuse an existing event loop and if no event
loop is available, a new event loop is created.

The cache of the FastAPI app is also refactored to use it's own mechanism.
It's now based on a dictionary of queues by root path by database,
where each queue is a pool of FastAPI app. This allows a better management
of the invalidation of the cache. It's now possible to invalidate
the cache of FastAPI app by root path without affecting the cache of others
root paths.
On server shutdown, ensure that created the event loops are closed properly.
defaultdict in python is not thread safe. Since this data structure
is used to store the cache of FastAPI apps, we must ensure that the
access to this cache is thread safe. This is done by using a lock
to protect the access to the cache.
This commit improves the lifecycle of the fastapi app cache.
It first ensures that the cache is effectively invalidated when changes
are made to the app configuration even if theses changes occur into an
other server instance.
It also remove the use of a locking mechanism put in place to ensure a thread
safe access to a value into the cache to avoid potential concurrency issue when
a default value is set to the cache at access time. This lock could lead
to unnecessary contention and reduce the performance benefits of queue.Queue's
fine-grained internal synchronization for a questionable gain. The only
expected gain was to avoid the useless creation of a queue.Queue instance
that would never be used since at the time of puting the value into the cache
we are sure that a value is already present into the dictionary.
Signed-off-by lmignon
Before this change, an eventloop thread was created on each instanciation of the ASGIMiddleware class. We want to avoid this behavior to avoid the creation of zombie threads
Signed-off-by sebastienbeau
Add a new test to ensure that if a retryable error occurs when processing a call to a base_rest endpoint, the retrying mechanism of odoo works as expected
In case of a retryable error, the initial error must bubble up to the retrying mechanism. If this kind of error is wrapped into another one, the retrying mechanism no more works
Signed-off-by lmignon
Signed-off-by lmignon
@ak-git-bot
Copy link

Hi @paradoxxxzero,
some modules you are maintaining are being modified, check this out!

Currently translated at 100.0% (3 of 3 strings)

Translation: rest-framework-16.0/rest-framework-16.0-fastapi_auth_jwt_demo
Translate-URL: https://translation.odoo-community.org/projects/rest-framework-16-0/rest-framework-16-0-fastapi_auth_jwt_demo/it/
Currently translated at 100.0% (43 of 43 strings)

Translation: rest-framework-16.0/rest-framework-16.0-fastapi
Translate-URL: https://translation.odoo-community.org/projects/rest-framework-16-0/rest-framework-16-0-fastapi/it/
@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from 1e08ade to ff9d6af Compare April 28, 2025 09:48
@SirPyTech SirPyTech marked this pull request as draft April 28, 2025 09:54
@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from ff9d6af to 1e08ade Compare April 28, 2025 09:57
@SirPyTech SirPyTech marked this pull request as ready for review April 28, 2025 10:05
@PicchiSeba
Copy link

PicchiSeba commented Apr 30, 2025

Regarding the multi-slash PR maybe we should wait to include it in its entirety until we receive some feedback (and I implement some tests).

I could extract the get_endpoint method without the multi-slash part and put it in its own PR and then apply my PR on it.
This way we have a common method to work on.

What do you think?

@SirPyTech
Copy link
Author

Regarding the multi-slash PR maybe we should wait to include it in its entirety until we receive some feedback (and I implement some tests).

I could extract the get_endpoint method without the multi-slash part and put it in its own PR and then apply my PR on it. This way we have a common method to work on.

What do you think?

Yes that's a good conservative solution.
So you'll create a simple refactoring PR that only extracts the occurrences of self.search([("root_path", "=", root_path)]) in a get_endpoint method, leaving the rest unchanged; that should be merged easily.

Then OCA#515 will build on the new PR to edit the get_endpoint implementation and root_path definition.

I will then include the new refactoring PR instead of OCA#515.

@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from 05fb39b to cfdb0e3 Compare June 25, 2025 10:05
@SirPyTech SirPyTech marked this pull request as ready for review June 25, 2025 10:06
@SirPyTech SirPyTech marked this pull request as draft June 26, 2025 07:45
@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from cfdb0e3 to f88ff23 Compare June 26, 2025 08:30
@SirPyTech SirPyTech marked this pull request as ready for review June 26, 2025 08:32
@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from f88ff23 to 29c911a Compare June 26, 2025 10:47
@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from 29c911a to b5429b3 Compare June 30, 2025 10:39
@SirPyTech SirPyTech force-pushed the 16.0-add-fastapi_log branch from b5429b3 to a1c02fa Compare June 30, 2025 10:41
@SirPyTech
Copy link
Author

There are several conflicts because https://github.com/akretion/rest-framework/tree/16.0-add-fastapi_log is not updated with https://github.com/OCA/rest-framework/tree/16.0, maybe it's time to move this PR to OCA?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.