Skip to content

Commit

Permalink
feat: structlog plugin & bug fixes (#2943)
Browse files Browse the repository at this point in the history
* feat(channels): Postgres backends (#2803)

* wip

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* some debugging

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* formatting

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* use a separate connection to publish/listen

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* reintroduce flaky

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix typing

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add psycopg backend

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix backend issues

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Undo test debugging changes

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* mark groups

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Ensure channel names ar quoted

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* sleep debugging

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* update docs

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add missing test

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix docs link

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add missing listener test

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Formatting

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix test typing

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix some coverage issue

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com>

* test skip sourcery

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* test(channels): Improve channels testing (#2838)

* Improve channels testing

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com>

* chore(typing): various pyright issues (#2897)

Fix various pyright issues

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* fix(channels): Trailing messages after unsubscribes (#2894)

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(cli): Add ``--schema`` and ``--exclude`` option to route CLI. (#2886)

* add exclude and schema cli options to route.

* updates per linting, mypy, and etc.

* fix some more mypy stuff.

* fix issue with linting.

* add doc for route cli options.

* fix issue with python3.8 not liking dict type.

* add exclude and schema cli options to route.

* updates per linting, mypy, and etc.

* fix some more mypy stuff.

* fix issue with linting.

* add doc for route cli options.

* fix issue with python3.8 not liking dict type.

* Update docs/usage/cli.rst

* Update litestar/cli/_utils.py

* fix malformed docs table.

---------

Co-authored-by: Jacob Coffee <jacob@z7x.org>

* test(CLI): Fix xdist issue (#2931)

Fix test for xdist

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(core): Replace `anyio.to_thread.run_sync` with native versions (#2937)

Replace anyio.to_thread.run_sync with native versions

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat: example app using structlog

* fix: updated structlog with request logging

* fix: lazy initialized structlog fix

* feat: add structlog plugin

* fix: adds `set_level` to all Logging configurations

* fix: check that the object has the `setLevel` method before calling

* feat: adds test for plugin

* fix: parameter naming for `set_level` abstract method

* feat(channels): Postgres backends (#2803)

* wip

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* some debugging

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* formatting

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* use a separate connection to publish/listen

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* reintroduce flaky

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix typing

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add psycopg backend

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix backend issues

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Undo test debugging changes

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* mark groups

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Ensure channel names ar quoted

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* sleep debugging

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* update docs

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add missing test

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix docs link

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add missing listener test

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Formatting

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix test typing

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix some coverage issue

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com>

* test skip sourcery

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* test(channels): Improve channels testing (#2838)

* Improve channels testing

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com>

* chore(typing): various pyright issues (#2897)

Fix various pyright issues

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* fix(channels): Trailing messages after unsubscribes (#2894)

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(cli): Add ``--schema`` and ``--exclude`` option to route CLI. (#2886)

* add exclude and schema cli options to route.

* updates per linting, mypy, and etc.

* fix some more mypy stuff.

* fix issue with linting.

* add doc for route cli options.

* fix issue with python3.8 not liking dict type.

* add exclude and schema cli options to route.

* updates per linting, mypy, and etc.

* fix some more mypy stuff.

* fix issue with linting.

* add doc for route cli options.

* fix issue with python3.8 not liking dict type.

* Update docs/usage/cli.rst

* Update litestar/cli/_utils.py

* fix malformed docs table.

---------

Co-authored-by: Jacob Coffee <jacob@z7x.org>

* test(CLI): Fix xdist issue (#2931)

Fix test for xdist

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(core): Replace `anyio.to_thread.run_sync` with native versions (#2937)

Replace anyio.to_thread.run_sync with native versions

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(channels): Postgres backends (#2803)

* wip

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* some debugging

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* formatting

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* use a separate connection to publish/listen

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* reintroduce flaky

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix typing

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add psycopg backend

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix backend issues

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Undo test debugging changes

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* mark groups

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Ensure channel names ar quoted

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* sleep debugging

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* update docs

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add missing test

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix docs link

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Add missing listener test

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Formatting

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix test typing

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* Fix some coverage issue

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com>

* test skip sourcery

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* test(channels): Improve channels testing (#2838)

* Improve channels testing

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com>

* chore(typing): various pyright issues (#2897)

Fix various pyright issues

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* fix(channels): Trailing messages after unsubscribes (#2894)

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(cli): Add ``--schema`` and ``--exclude`` option to route CLI. (#2886)

* add exclude and schema cli options to route.

* updates per linting, mypy, and etc.

* fix some more mypy stuff.

* fix issue with linting.

* add doc for route cli options.

* fix issue with python3.8 not liking dict type.

* add exclude and schema cli options to route.

* updates per linting, mypy, and etc.

* fix some more mypy stuff.

* fix issue with linting.

* add doc for route cli options.

* fix issue with python3.8 not liking dict type.

* Update docs/usage/cli.rst

* Update litestar/cli/_utils.py

* fix malformed docs table.

---------

Co-authored-by: Jacob Coffee <jacob@z7x.org>

* test(CLI): Fix xdist issue (#2931)

Fix test for xdist

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat(core): Replace `anyio.to_thread.run_sync` with native versions (#2937)

Replace anyio.to_thread.run_sync with native versions

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>

* feat: structlog detects tty by default

* chore: linting fixes

* fix: color code correction

* fix: adjusted color code to be more visible

* fix: additional config settings

* feat: enable pretty-print in TTY

* fix: apply rich configuration

* fix: updated formatting to align with other messages

* chore: trim whitespace

---------

Signed-off-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: Janek Nouvertné <provinzkraut@posteo.de>
Co-authored-by: Janek Nouvertné <25355197+provinzkraut@users.noreply.github.com>
Co-authored-by: andrew do <andrewddo@gmail.com>
Co-authored-by: Jacob Coffee <jacob@z7x.org>
  • Loading branch information
5 people committed Feb 3, 2024
1 parent 921c9ec commit 3eb29f5
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 50 deletions.
8 changes: 4 additions & 4 deletions docs/usage/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ Using StructLog
^^^^^^^^^^^^^^^

`StructLog <https://www.structlog.org/en/stable/>`_ is a powerful structured-logging library. Litestar ships with a dedicated
logging config for using it:
logging plugin and config for using it:

.. code-block:: python
from litestar import Litestar, Request, get
from litestar.logging import StructLoggingConfig
from litestar.plugins.structlog import StructlogPlugin
@get("/")
Expand All @@ -127,9 +127,9 @@ logging config for using it:
return None
logging_config = StructLoggingConfig()
structlog_plugin = StructlogPlugin()
app = Litestar(route_handlers=[my_router_handler], logging_config=logging_config)
app = Litestar(route_handlers=[my_router_handler], plugins=[StructlogPlugin()])
Subclass Logging Configs
^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
8 changes: 7 additions & 1 deletion litestar/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,13 @@ def debug(self) -> bool:

@debug.setter
def debug(self, value: bool) -> None:
if self.logger:
"""Sets the debug logging level for the application.
When possible, it calls the `self.logging_config.set_level` method. This allows for implementation specific code and APIs to be called.
"""
if self.logger and self.logging_config:
self.logging_config.set_level(self.logger, logging.DEBUG if value else logging.INFO)
elif self.logger and hasattr(self.logger, "setLevel"):
self.logger.setLevel(logging.DEBUG if value else logging.INFO)
if isinstance(self.logging_config, LoggingConfig):
self.logging_config.loggers["litestar"]["level"] = "DEBUG" if value else "INFO"
Expand Down
123 changes: 105 additions & 18 deletions litestar/logging/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def _default_exception_logging_handler(logger: Logger, scope: Scope, tb: list[st

if is_struct_logger:
logger.exception(
"uncaught exception",
"Uncaught Exception",
connection_type=scope["type"],
path=scope["path"],
traceback="".join(tb[-traceback_line_limit:]),
Expand Down Expand Up @@ -135,6 +135,11 @@ def configure(self) -> GetLogger:
"""
raise NotImplementedError("abstract method")

@staticmethod
def set_level(logger: Any, level: int) -> None:
"""Provides a consistent interface to call `setLevel` for all loggers."""
raise NotImplementedError("abstract method")


@dataclass
class LoggingConfig(BaseLoggingConfig):
Expand Down Expand Up @@ -234,32 +239,75 @@ def configure(self) -> GetLogger:
config.dictConfig(values)
return cast("Callable[[str], Logger]", getLogger)

@staticmethod
def set_level(logger: Logger, level: int) -> None:
"""Provides a consistent interface to call `setLevel` for all loggers."""
logger.setLevel(level)


def default_json_serializer(value: Any, default: Callable[[Any], Any] | None = None) -> bytes:
return encode_json(value=value, serializer=default)


def default_structlog_processors() -> list[Processor] | None: # pyright: ignore
def default_structlog_processors(as_json: bool = True) -> list[Processor]: # pyright: ignore
"""Set the default processors for structlog.
Returns:
An optional list of processors.
"""
try:
import structlog

from structlog.dev import RichTracebackFormatter

if as_json:
return [
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.format_exc_info,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer(serializer=default_json_serializer),
]
return [
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.format_exc_info,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer(serializer=default_json_serializer),
structlog.dev.ConsoleRenderer(
colors=True, exception_formatter=RichTracebackFormatter(max_frames=1, show_locals=False, width=80)
),
]

except ImportError:
return None
return []


def default_structlog_standard_lib_processors(as_json: bool = True) -> list[Processor]: # pyright: ignore
"""Set the default processors for structlog stdlib.
Returns:
An optional list of processors.
"""
try:
import structlog
from structlog.dev import RichTracebackFormatter

if as_json:
return [
structlog.stdlib.add_log_level,
structlog.stdlib.ExtraAdder(),
structlog.processors.JSONRenderer(serializer=default_json_serializer),
]
return [
structlog.stdlib.add_log_level,
structlog.stdlib.ExtraAdder(),
structlog.dev.ConsoleRenderer(
colors=True, exception_formatter=RichTracebackFormatter(max_frames=1, show_locals=False, width=80)
),
]
except ImportError:
return []


def default_wrapper_class() -> type[BindableLogger] | None: # pyright: ignore
def default_wrapper_class(log_level: int = INFO) -> type[BindableLogger] | None: # pyright: ignore
"""Set the default wrapper class for structlog.
Returns:
Expand All @@ -269,12 +317,12 @@ def default_wrapper_class() -> type[BindableLogger] | None: # pyright: ignore
try:
import structlog

return structlog.make_filtering_bound_logger(INFO)
return structlog.make_filtering_bound_logger(log_level)
except ImportError:
return None


def default_logger_factory() -> Callable[..., WrappedLogger] | None:
def default_logger_factory(as_json: bool = True) -> Callable[..., WrappedLogger] | None:
"""Set the default logger factory for structlog.
Returns:
Expand All @@ -283,7 +331,9 @@ def default_logger_factory() -> Callable[..., WrappedLogger] | None:
try:
import structlog

return structlog.BytesLoggerFactory()
if as_json:
return structlog.BytesLoggerFactory()
return structlog.WriteLoggerFactory()
except ImportError:
return None

Expand All @@ -296,13 +346,18 @@ class StructLoggingConfig(BaseLoggingConfig):
- requires ``structlog`` to be installed.
"""

processors: list[Processor] | None = field(default_factory=default_structlog_processors) # pyright: ignore
processors: list[Processor] | None = field(default=None) # pyright: ignore
"""Iterable of structlog logging processors."""
wrapper_class: type[BindableLogger] | None = field(default_factory=default_wrapper_class) # pyright: ignore
standard_lib_logging_config: LoggingConfig | None = field(default=None) # pyright: ignore
"""Optional customized standard logging configuration.
Use this when you need to modify the standard library outside of the Structlog pre-configured implementation.
"""
wrapper_class: type[BindableLogger] | None = field(default=None) # pyright: ignore
"""Structlog bindable logger."""
context_class: dict[str, Any] | None = None
"""Context class (a 'contextvar' context) for the logger."""
logger_factory: Callable[..., WrappedLogger] | None = field(default_factory=default_logger_factory)
logger_factory: Callable[..., WrappedLogger] | None = field(default=None) # pyright: ignore
"""Logger factory to use."""
cache_logger_on_first_use: bool = field(default=True)
"""Whether to cache the logger configuration and reuse."""
Expand All @@ -312,12 +367,34 @@ class StructLoggingConfig(BaseLoggingConfig):
"""Max number of lines to print for exception traceback"""
exception_logging_handler: ExceptionLoggingHandler | None = field(default=None)
"""Handler function for logging exceptions."""
pretty_print_tty: bool = field(default=True)
"""Pretty print log output when run from an interactive terminal."""

def __post_init__(self) -> None:
if self.processors is None:
self.processors = default_structlog_processors(not sys.stderr.isatty() and self.pretty_print_tty)
if self.logger_factory is None:
self.logger_factory = default_logger_factory(not sys.stderr.isatty() and self.pretty_print_tty)
if self.log_exceptions != "never" and self.exception_logging_handler is None:
self.exception_logging_handler = _default_exception_logging_handler_factory(
is_struct_logger=True, traceback_line_limit=self.traceback_line_limit
)
try:
import structlog

if self.standard_lib_logging_config is None:
self.standard_lib_logging_config = LoggingConfig(
formatters={
"standard": {
"()": structlog.stdlib.ProcessorFormatter,
"processors": default_structlog_standard_lib_processors(
as_json=not sys.stderr.isatty() and self.pretty_print_tty
),
}
}
)
except ImportError:
self.standard_lib_logging_config = LoggingConfig()

def configure(self) -> GetLogger:
"""Return logger with the given configuration.
Expand All @@ -326,13 +403,11 @@ def configure(self) -> GetLogger:
A 'logging.getLogger' like function.
"""
try:
import structlog # noqa: F401
import structlog
except ImportError as e:
raise MissingDependencyException("structlog") from e

from structlog import configure, get_logger

configure(
structlog.configure(
**{
k: v
for k, v in asdict(self).items()
Expand All @@ -342,7 +417,19 @@ def configure(self) -> GetLogger:
"log_exceptions",
"traceback_line_limit",
"exception_logging_handler",
"pretty_print_tty",
)
}
)
return get_logger
return structlog.get_logger

@staticmethod
def set_level(logger: Logger, level: int) -> None:
"""Provides a consistent interface to call `setLevel` for all loggers."""

try:
import structlog

structlog.configure(wrapper_class=structlog.make_filtering_bound_logger(level))
except ImportError:
""""""
61 changes: 61 additions & 0 deletions litestar/plugins/structlog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from litestar.cli._utils import console
from litestar.logging.config import StructLoggingConfig
from litestar.middleware.logging import LoggingMiddlewareConfig
from litestar.plugins import CLIPluginProtocol, InitPluginProtocol

if TYPE_CHECKING:
from click import Group

from litestar.config.app import AppConfig


@dataclass
class StructlogConfig:
structlog_logging_config: StructLoggingConfig = field(default_factory=StructLoggingConfig)
"""Structlog Logging configuration for Litestar. See ``litestar.logging.config.StructLoggingConfig``` for details."""
middleware_logging_config: LoggingMiddlewareConfig = field(default_factory=LoggingMiddlewareConfig)
"""Middleware logging config."""
enable_middleware_logging: bool = True
"""Enable request logging."""


class StructlogPlugin(InitPluginProtocol, CLIPluginProtocol):
"""Structlog Plugin."""

__slots__ = ("_config",)

def __init__(self, config: StructlogConfig | None = None) -> None:
if config is None:
config = StructlogConfig()
self._config = config
super().__init__()

def on_cli_init(self, cli: Group) -> None:
return super().on_cli_init(cli)

def on_app_init(self, app_config: AppConfig) -> AppConfig:
"""Structlog Plugin
Args:
app_config: The :class:`AppConfig <litestar.config.app.AppConfig>` instance.
Returns:
The app config object.
"""
if app_config.logging_config is not None and isinstance(app_config.logging_config, StructLoggingConfig):
console.print(
"[red dim]* Found pre-configured `StructLoggingConfig` on the `app` instance. Skipping configuration.[/]",
)
else:
app_config.logging_config = self._config.structlog_logging_config
app_config.logging_config.configure()
if self._config.structlog_logging_config.standard_lib_logging_config is not None:
self._config.structlog_logging_config.standard_lib_logging_config.configure()
if self._config.enable_middleware_logging:
app_config.middleware.append(self._config.middleware_logging_config.middleware)
return app_config # pragma: no cover
3 changes: 1 addition & 2 deletions litestar/response/sse.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ async def _async_generator(self) -> AsyncGenerator[bytes, None]:
yield await sync_to_thread(self._call_next)
except ValueError:
async for value in self.content_async_iterator:
data = self.ensure_bytes(value, DEFAULT_SEPARATOR)
yield data
yield self.ensure_bytes(value, DEFAULT_SEPARATOR)
break


Expand Down
Loading

0 comments on commit 3eb29f5

Please sign in to comment.