Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion lite_bootstrap/bootstrappers/litestar_bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from litestar import status_codes
from litestar.config.app import AppConfig
from litestar.config.cors import CORSConfig
from litestar.logging.config import LoggingConfig as LitestarStandardLoggingConfig
from litestar.logging.config import StructLoggingConfig
from litestar.middleware.logging import LoggingMiddlewareConfig
from litestar.openapi import OpenAPIConfig
Expand Down Expand Up @@ -187,6 +188,16 @@ def _build_logging_middleware_config(self) -> "LoggingMiddlewareConfig":
exclude=excluded_paths or None,
)

def _build_standard_lib_logging_config(self) -> "LitestarStandardLoggingConfig":
"""Leave stdlib output to lite-bootstrap: Litestar's default config replaces the root handler."""
return LitestarStandardLoggingConfig(
configure_root_logger=False,
handlers={"console": {"class": "logging.NullHandler"}, "queue_listener": {"class": "logging.NullHandler"}},
loggers={
"litestar": {"level": self.bootstrap_config.logging_log_level, "handlers": [], "propagate": False}
},
)

def _configure_structlog_loggers(self) -> None:
"""Register Litestar's StructlogPlugin instead of calling ``structlog.configure`` directly."""
self.bootstrap_config.application_config.plugins.append(
Expand All @@ -198,7 +209,7 @@ def _configure_structlog_loggers(self) -> None:
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
pretty_print_tty=False,
standard_lib_logging_config=None,
standard_lib_logging_config=self._build_standard_lib_logging_config(),
),
# Litestar defaults this to True, which logs full request/response bodies.
enable_middleware_logging=self.bootstrap_config.litestar_logging_middleware_enabled,
Expand Down
26 changes: 26 additions & 0 deletions tests/test_litestar_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import inspect
import json
import logging
import logging.handlers
import sys
import typing
import warnings
Expand Down Expand Up @@ -309,6 +310,31 @@ async def _login_handler(data: dict[str, str]) -> dict[str, str]:
return log_lines


def test_litestar_logging_keeps_lite_bootstrap_root_handler(litestar_config: LitestarConfig) -> None:
application = LitestarBootstrapper(bootstrap_config=litestar_config).bootstrap()
with TestClient(app=application):
root_handlers = logging.getLogger().handlers
assert not any(isinstance(handler, logging.handlers.QueueHandler) for handler in root_handlers)
assert any(isinstance(handler.formatter, structlog.stdlib.ProcessorFormatter) for handler in root_handlers)


def test_litestar_access_log_has_one_handler(litestar_config: LitestarConfig) -> None:
@litestar.get("/ping")
async def _ping_handler() -> dict[str, bool]:
return {"ok": True}

config = dataclasses.replace(
litestar_config,
litestar_logging_middleware_enabled=True,
application_config=AppConfig(route_handlers=[_ping_handler]),
)
application = LitestarBootstrapper(bootstrap_config=config).bootstrap()
with TestClient(app=application) as client:
assert client.get("/ping").status_code == status_codes.HTTP_200_OK
litestar_handlers = logging.getLogger("litestar").handlers
assert [type(handler) for handler in litestar_handlers] == [logging.handlers.MemoryHandler]


def test_litestar_access_logging_disabled_by_default(litestar_config: LitestarConfig) -> None:
log_lines = _post_password(litestar_config)

Expand Down
Loading