Skip to content

Commit 2506dcf

Browse files
authored
Merge pull request #8 from redb0/logger-filter
Logger filter
2 parents 971cbec + a92d89e commit 2506dcf

6 files changed

Lines changed: 20 additions & 4 deletions

File tree

docs_src/example_8.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class LogWithUser(LogModel, table=True):
5959
'login_type': ['session', 'login_type'],
6060
'name': ['session', 'name'],
6161
},
62+
available_loggers=['api.access'],
6263
)
6364

6465
logger = structlog.get_logger()

fastapi_structlog/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import logging
99
import logging.handlers
10-
from collections.abc import Callable
10+
from collections.abc import Callable, Sequence
1111
from typing import Any, Optional, Union
1212

1313
from sqlalchemy.engine.url import URL
@@ -32,6 +32,7 @@ def setup_logger( # noqa: PLR0913
3232
key_aliases: Optional[dict[str, list[str]]] = None,
3333
key_handlers: Optional[dict[str, Callable[[Any, logging.LogRecord], Any]]] = None,
3434
search_paths: Optional[dict[str, list[str]]] = None,
35+
available_loggers: Optional[Sequence[str]] = None,
3536
) -> Optional[logging.handlers.QueueListener]:
3637
"""Initialize the logger with the configuration.
3738
@@ -50,6 +51,8 @@ def setup_logger( # noqa: PLR0913
5051
search_paths (Optional[dict[str, list[str]]], optional): Search paths
5152
for model attributes. This can be useful when searching for
5253
attributes in nested log structures.
54+
available_loggers (Optional[Sequence[str]], optional): Names of the
55+
loggers that will be included in the database.
5356
"""
5457
configurator = LoggerConfigurator(settings_)
5558
configurator.add_base_handler()
@@ -79,6 +82,7 @@ def setup_logger( # noqa: PLR0913
7982
key_aliases=key_aliases,
8083
search_paths=search_paths,
8184
key_handlers=key_handlers,
85+
available_loggers=available_loggers
8286
),
8387
)
8488

fastapi_structlog/db_handler/handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
import logging.handlers
77
from abc import abstractmethod
8-
from collections.abc import Callable
8+
from collections.abc import Callable, Sequence
99
from typing import Any, Generic, Optional, TypeVar, Union, cast
1010

1111
from sqlalchemy import create_engine
@@ -42,6 +42,7 @@ def __init__(
4242
key_aliases: Optional[dict[str, list[str]]] = None,
4343
search_paths: Optional[dict[str, list[str]]] = None,
4444
key_handlers: Optional[dict[str, Callable[[Any, logging.LogRecord], Any]]] = None,
45+
available_loggers: Optional[Sequence[str]] = None,
4546
) -> None:
4647
super().__init__(level)
4748
self.model = model
@@ -52,6 +53,7 @@ def __init__(
5253
self.key_aliases = key_aliases or {}
5354
self.search_paths = search_paths or {}
5455
self.key_handlers = key_handlers or {}
56+
self.available_loggers = set(available_loggers) if available_loggers else set()
5557

5658
@property
5759
def loop(self) -> asyncio.AbstractEventLoop:
@@ -74,6 +76,9 @@ def construct_message(self, record: logging.LogRecord) -> T_:
7476

7577
def emit(self, record: logging.LogRecord) -> None:
7678
"""Save the message in the database."""
79+
if self.available_loggers and record.name not in self.available_loggers:
80+
return
81+
7782
message = self.construct_message(record)
7883
if self.db_url.drivername == 'postgresql+asyncpg':
7984
self.loop.run_until_complete(self._async_emit(message))

fastapi_structlog/log.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging.handlers
44
import sys
55
from abc import abstractmethod
6-
from collections.abc import Callable
6+
from collections.abc import Callable, Sequence
77
from logging.handlers import TimedRotatingFileHandler
88
from pathlib import Path
99
from queue import SimpleQueue
@@ -345,6 +345,7 @@ def create_handler( # noqa: PLR0913
345345
key_aliases: Optional[dict[str, list[str]]] = None,
346346
search_paths: Optional[dict[str, list[str]]] = None,
347347
key_handlers: Optional[dict[str, Callable[[Any, logging.LogRecord], Any]]] = None,
348+
available_loggers: Optional[Sequence[str]] = None,
348349
**_: Any, # noqa: ANN401
349350
) -> DatabaseHandler[T_]:
350351
"""Create a handler."""
@@ -361,6 +362,7 @@ def create_handler( # noqa: PLR0913
361362
key_aliases=key_aliases,
362363
search_paths=search_paths,
363364
key_handlers=key_handlers,
365+
available_loggers=available_loggers,
364366
)
365367

366368

fastapi_structlog/middleware/structlog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: #
4343
structlog.contextvars.bind_contextvars(request_id=request_id)
4444

4545
request = {
46-
'method': scope['method'],
46+
'method': scope.get('method'),
4747
'path': get_path_with_query_string(scope),
4848
'client_addr': get_client_addr(scope),
4949
'user_agent': get_user_agent(scope),

fastapi_structlog/middleware/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ def get_path_with_query_string(scope: Scope) -> str:
3030
Returns:
3131
str: URL with query parameters
3232
"""
33+
if 'path' not in scope:
34+
return '-'
3335
path_with_query_string = quote(scope['path'])
3436
if raw_query_string := scope['query_string']:
3537
query_string = raw_query_string.decode('ascii')
@@ -46,6 +48,8 @@ def get_user_agent(scope: Scope) -> str:
4648
Returns:
4749
str: User-agent or '-' if it is not presented or for exceptions.
4850
"""
51+
if 'headers' not in scope:
52+
return '-'
4953
headers: list[tuple[bytes, bytes]] = scope.get('headers')
5054
if not headers:
5155
return '-'

0 commit comments

Comments
 (0)