Skip to content

Commit 16fa971

Browse files
paradoxxxzeroKev-Roche
authored andcommitted
[ADD] fastapi_log
1 parent 2af1abb commit 16fa971

File tree

19 files changed

+1281
-0
lines changed

19 files changed

+1281
-0
lines changed

fastapi_log/README.rst

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
===========
2+
Fastapi Log
3+
===========
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:ef0c0bceb8ae27bcfebaebc22e2fb4747475f2a2c60dd2d410bc40b6efee9b6a
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github
20+
:target: https://github.com/OCA/rest-framework/tree/16.0/fastapi_log
21+
:alt: OCA/rest-framework
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/rest-framework-16-0/rest-framework-16-0-fastapi_log
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=16.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module allows an endpoint to activate full request logging in a
32+
database model.
33+
34+
It is useful to debug production issues or to monitor the usage of a
35+
specific endpoint.
36+
37+
**Table of contents**
38+
39+
.. contents::
40+
:local:
41+
42+
Usage
43+
=====
44+
45+
To activate logging for an endpoint, you have to check the
46+
``Log Requests`` checkbox in the endpoint's configuration. This will log
47+
all requests and responses for that endpoint.
48+
49+
A smart button will be displayed in the endpoint's form view to access
50+
the endpoint logs. A global log view is also available in the
51+
``FastAPI Logs`` menu.
52+
53+
Bug Tracker
54+
===========
55+
56+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rest-framework/issues>`_.
57+
In case of trouble, please check there if your issue has already been reported.
58+
If you spotted it first, help us to smash it by providing a detailed and welcomed
59+
`feedback <https://github.com/OCA/rest-framework/issues/new?body=module:%20fastapi_log%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
60+
61+
Do not contact contributors directly about support or help with technical issues.
62+
63+
Credits
64+
=======
65+
66+
Authors
67+
-------
68+
69+
* Akretion
70+
71+
Contributors
72+
------------
73+
74+
- Florian Mounier florian.mounier@akretion.com
75+
76+
Maintainers
77+
-----------
78+
79+
This module is maintained by the OCA.
80+
81+
.. image:: https://odoo-community.org/logo.png
82+
:alt: Odoo Community Association
83+
:target: https://odoo-community.org
84+
85+
OCA, or the Odoo Community Association, is a nonprofit organization whose
86+
mission is to support the collaborative development of Odoo features and
87+
promote its widespread use.
88+
89+
.. |maintainer-paradoxxxzero| image:: https://github.com/paradoxxxzero.png?size=40px
90+
:target: https://github.com/paradoxxxzero
91+
:alt: paradoxxxzero
92+
93+
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
94+
95+
|maintainer-paradoxxxzero|
96+
97+
This module is part of the `OCA/rest-framework <https://github.com/OCA/rest-framework/tree/16.0/fastapi_log>`_ project on GitHub.
98+
99+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

fastapi_log/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import models
2+
from . import fastapi_dispatcher

fastapi_log/__manifest__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2025 Akretion (http://www.akretion.com).
2+
# @author Florian Mounier <florian.mounier@akretion.com>
3+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
4+
5+
{
6+
"name": "Fastapi Log",
7+
"version": "16.0.1.0.0",
8+
"author": "Akretion, Odoo Community Association (OCA)",
9+
"summary": "Log Fastapi requests in database",
10+
"category": "Tools",
11+
"depends": ["fastapi"],
12+
"website": "https://github.com/OCA/rest-framework",
13+
"data": [
14+
"security/res_groups.xml",
15+
"security/ir_model_access.xml",
16+
"views/fastapi_endpoint_views.xml",
17+
"views/fastapi_log_views.xml",
18+
],
19+
"maintainers": ["paradoxxxzero"],
20+
"demo": [],
21+
"installable": True,
22+
"license": "AGPL-3",
23+
}

fastapi_log/fastapi_dispatcher.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright 2025 Akretion (http://www.akretion.com).
2+
# @author Florian Mounier <florian.mounier@akretion.com>
3+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
4+
import logging
5+
6+
from odoo import registry, tools
7+
from odoo.http import _dispatchers
8+
9+
from odoo.addons.fastapi.fastapi_dispatcher import (
10+
FastApiDispatcher as BaseFastApiDispatcher,
11+
)
12+
13+
_logger = logging.getLogger(__name__)
14+
15+
16+
# Inherit from last registered fastapi dispatcher
17+
# This handles multiple overload of dispatchers
18+
class FastApiDispatcher(_dispatchers.get("fastapi", BaseFastApiDispatcher)):
19+
routing_type = "fastapi"
20+
21+
def dispatch(self, endpoint, args):
22+
self.request.params = {}
23+
environ = self._get_environ()
24+
root_path = "/" + environ["PATH_INFO"].split("/")[1]
25+
fastapi_endpoint = (
26+
self.request.env["fastapi.endpoint"]
27+
.sudo()
28+
.search([("root_path", "=", root_path)])
29+
)
30+
if fastapi_endpoint.log_requests:
31+
log = None
32+
try:
33+
if tools.config["test_enable"]:
34+
cr = getattr(
35+
self.request.env.registry, "test_log_cr", self.request.env.cr
36+
)
37+
else:
38+
# Create an independent cursor
39+
cr = registry(self.request.env.cr.dbname).cursor()
40+
41+
env = self.request.env(cr=cr, su=True)
42+
try:
43+
# cf fastapi _get_environ
44+
request = self.request.httprequest._HTTPRequest__wrapped
45+
except AttributeError:
46+
request = self.request.httprequest
47+
48+
log = env["fastapi.log"].log_request(
49+
request, environ, fastapi_endpoint.id
50+
)
51+
except Exception as e:
52+
_logger.warning("Failed to log request", exc_info=e)
53+
54+
try:
55+
response = super().dispatch(endpoint, args)
56+
except Exception as e:
57+
try:
58+
log and log.log_exception(e)
59+
except Exception as e:
60+
_logger.warning("Failed to log exception", exc_info=e)
61+
raise e
62+
else:
63+
try:
64+
log and log.log_response(response)
65+
except Exception as e:
66+
_logger.warning("Failed to log response", exc_info=e)
67+
finally:
68+
if not tools.config["test_enable"]:
69+
try:
70+
cr.commit() # pylint: disable=E8102
71+
finally:
72+
cr.close()
73+
return response
74+
75+
else:
76+
return super().dispatch(endpoint, args)

fastapi_log/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import fastapi_endpoint
2+
from . import fastapi_log
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2025 Akretion (http://www.akretion.com).
2+
# @author Florian Mounier <florian.mounier@akretion.com>
3+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
4+
5+
from odoo import api, fields, models
6+
7+
8+
class FastapiEndpoint(models.Model):
9+
_inherit = "fastapi.endpoint"
10+
11+
log_requests = fields.Boolean(
12+
help="Log requests in database.",
13+
)
14+
15+
fastapi_log_ids = fields.One2many(
16+
"fastapi.log",
17+
"endpoint_id",
18+
string="Logs",
19+
)
20+
21+
fastapi_log_count = fields.Integer(
22+
compute="_compute_fastapi_log_count",
23+
string="Logs Count",
24+
)
25+
26+
@api.depends("fastapi_log_ids")
27+
def _compute_fastapi_log_count(self):
28+
data = self.env["fastapi.log"].read_group(
29+
[("endpoint_id", "in", self.ids)],
30+
["endpoint_id"],
31+
["endpoint_id"],
32+
)
33+
mapped_data = {m["endpoint_id"][0]: m["endpoint_id_count"] for m in data}
34+
for record in self:
35+
record.fastapi_log_count = mapped_data.get(record.id, 0)

0 commit comments

Comments
 (0)