|
2 | 2 |
|
3 | 3 | import logging |
4 | 4 | import traceback |
5 | | -from typing import Callable, Tuple, Optional, Dict, Any, Iterable, Union |
| 5 | +from typing import Callable, Tuple, Optional, Dict, Any, Iterable, Union, Awaitable |
6 | 6 | from typing import Literal |
| 7 | +import inspect |
| 8 | + |
7 | 9 |
|
8 | 10 | from fastapi import FastAPI, Request |
9 | 11 | from fastapi.encoders import jsonable_encoder |
|
40 | 42 |
|
41 | 43 | LogLevelLiteral = Literal[10, 20, 30, 40, 50] |
42 | 44 | HeaderKeys = Tuple[str, ...] |
43 | | -ExtraLogFields = Callable[[Request, Optional[BaseException]], Dict[str, Any]] |
| 45 | + |
| 46 | +ExtraLogFields = Callable[ |
| 47 | + [Callable[[Request, Optional[BaseException]], Dict[str, Any]]], |
| 48 | + Callable[[Request, Optional[BaseException]], Awaitable[Dict[str, Any]]] |
| 49 | +] |
44 | 50 |
|
45 | 51 |
|
46 | 52 | def register_exception_handlers( |
@@ -115,6 +121,8 @@ def register_exception_handlers( |
115 | 121 | extra_log_fields : Callable[[Request, Optional[BaseException]], Dict[str, Any]] | None, default=None |
116 | 122 | A hook to inject **custom** fields into the log `meta`. Receives `(request, exc)` and must return a dict. |
117 | 123 | Useful for business context (tenant_id, feature flags, masked user ids, etc.). |
| 124 | + def my_fields(req, exc): ... |
| 125 | + async def my_fields(req, exc): ... |
118 | 126 | Example: |
119 | 127 | ```python |
120 | 128 | def my_extra_fields(req, exc): |
@@ -364,9 +372,12 @@ async def api_exception_handler(request: Request, exc: APIException): |
364 | 372 |
|
365 | 373 | if extra_log_fields: |
366 | 374 | try: |
367 | | - meta.update(extra_log_fields(request, exc)) |
| 375 | + result = extra_log_fields(request, exc) |
| 376 | + if inspect.isawaitable(result): |
| 377 | + result = await result |
| 378 | + if isinstance(result, dict): |
| 379 | + meta.update(result) |
368 | 380 | except Exception: |
369 | | - # Avoid breaking the handler due to user hook errors |
370 | 381 | pass |
371 | 382 |
|
372 | 383 | if log_traceback and effective_level <= logging.DEBUG: |
|
0 commit comments