Skip to content

Commit b1d9a6a

Browse files
committed
Send logs to Matrix asynchronously
1 parent 513a563 commit b1d9a6a

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

app/core/utils/log.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Any
88

99
import uvicorn
10+
from fastapi import BackgroundTasks
1011

1112
from app.core.utils.config import Settings
1213

@@ -78,7 +79,7 @@ class console_color:
7879

7980
# Logging config
8081
# See https://docs.python.org/3/library/logging.config.html#logging-config-dictschema
81-
def get_config_dict(self, settings: Settings):
82+
def _get_config_dict(self, settings: Settings):
8283
# We can't use a dependency to access settings as this function is not an endpoint. The object must thus be passed as a parameter.
8384

8485
# /!\ WARNING /!\
@@ -121,6 +122,7 @@ def get_config_dict(self, settings: Settings):
121122
# Send error to a Matrix server. If credentials are not set in settings, the handler will be disabled
122123
"formatter": "matrix",
123124
"class": "app.utils.loggers_tools.matrix_handler.MatrixHandler",
125+
"background_tasks": BackgroundTasks,
124126
"room_id": settings.MATRIX_LOG_ERROR_ROOM_ID,
125127
"token": settings.MATRIX_TOKEN,
126128
"server_base_url": settings.MATRIX_SERVER_BASE_URL,
@@ -133,6 +135,7 @@ def get_config_dict(self, settings: Settings):
133135
# Send error to a Matrix server. If credentials are not set in settings, the handler will be disabled
134136
"formatter": "matrix",
135137
"class": "app.utils.loggers_tools.matrix_handler.MatrixHandler",
138+
"background_tasks": BackgroundTasks,
136139
"room_id": settings.MATRIX_LOG_AMAP_ROOM_ID,
137140
"token": settings.MATRIX_TOKEN,
138141
"server_base_url": settings.MATRIX_SERVER_BASE_URL,
@@ -398,7 +401,7 @@ def initialize_loggers(self, settings: Settings):
398401
# If logs/ folder does not exist, the logging module won't be able to create file handlers
399402
Path("logs/").mkdir(parents=True, exist_ok=True)
400403

401-
config_dict = self.get_config_dict(settings=settings)
404+
config_dict = self._get_config_dict(settings=settings)
402405
logging.config.dictConfig(config_dict)
403406

404407
loggers = [logging.getLogger(name) for name in config_dict["loggers"]]

app/utils/communication/matrix.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Any
22

3-
import requests
3+
import httpx
44

55
from app.types.exceptions import MatrixRequestError, MatrixSendMessageError
66

@@ -24,7 +24,7 @@ def __init__(
2424

2525
self.access_token = token
2626

27-
def post(
27+
async def post(
2828
self,
2929
url: str,
3030
json: dict[str, Any],
@@ -43,15 +43,21 @@ def post(
4343
if "Authorization" not in headers:
4444
headers["Authorization"] = "Bearer " + self.access_token
4545

46-
response = requests.post(url, json=json, headers=headers, timeout=10)
4746
try:
47+
async with httpx.AsyncClient() as client:
48+
response = await client.post(
49+
url,
50+
json=json,
51+
headers=headers,
52+
timeout=10,
53+
)
4854
response.raise_for_status()
49-
except requests.exceptions.HTTPError as err:
55+
except httpx.RequestError as err:
5056
raise MatrixRequestError() from err
5157

5258
return response.json()
5359

54-
def send_message(self, room_id: str, formatted_body: str) -> None:
60+
async def send_message(self, room_id: str, formatted_body: str) -> None:
5561
"""
5662
Send a message to the room `room_id`.
5763
`formatted_body` can contain html formatted text
@@ -71,6 +77,6 @@ def send_message(self, room_id: str, formatted_body: str) -> None:
7177
}
7278

7379
try:
74-
self.post(url, json=data, headers=None)
80+
await self.post(url, json=data, headers=None)
7581
except MatrixRequestError as error:
7682
raise MatrixSendMessageError(room_id=room_id) from error

app/utils/loggers_tools/matrix_handler.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
from logging import StreamHandler
33

4+
from fastapi import BackgroundTasks
45
from typing_extensions import override
56

67
from app.utils.communication.matrix import Matrix
@@ -21,6 +22,7 @@ class MatrixHandler(StreamHandler):
2122

2223
def __init__(
2324
self,
25+
background_tasks: BackgroundTasks,
2426
room_id: str,
2527
token: str,
2628
server_base_url: str | None,
@@ -30,6 +32,7 @@ def __init__(
3032
super().__init__()
3133
self.setLevel(level)
3234

35+
self.background_tasks = background_tasks
3336
self.room_id = room_id
3437
self.enabled = enabled
3538
if self.enabled:
@@ -42,9 +45,12 @@ def __init__(
4245
def emit(self, record):
4346
if self.enabled:
4447
msg = self.format(record)
45-
4648
try:
47-
self.matrix.send_message(self.room_id, msg)
49+
self.background_tasks.add_task(
50+
self.matrix.send_message,
51+
room_id=self.room_id,
52+
formatted_body=msg,
53+
)
4854
# We should catch and log any error, as Python may discarded them in production
4955
except Exception as err:
5056
# We use warning level so that the message is not sent to matrix again

0 commit comments

Comments
 (0)