From 8e4f1ddd73da9dc8d6a0fac2354e26d18c324b69 Mon Sep 17 00:00:00 2001 From: John | Elite Encoder Date: Tue, 14 Jul 2026 20:42:37 -0400 Subject: [PATCH 1/2] feat: add package-wide configure_logging and LOG_LEVEL support --- examples/write_frames.py | 3 +++ src/livepeer_gateway/__init__.py | 6 +++++ src/livepeer_gateway/logging_config.py | 33 ++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 src/livepeer_gateway/logging_config.py diff --git a/examples/write_frames.py b/examples/write_frames.py index 05b33ef..3614413 100644 --- a/examples/write_frames.py +++ b/examples/write_frames.py @@ -4,10 +4,12 @@ import av +from livepeer_gateway import configure_logging from livepeer_gateway.errors import LivepeerGatewayError from livepeer_gateway.lv2v import StartJobRequest, start_lv2v from livepeer_gateway.media_publish import MediaPublishConfig, VideoOutputConfig + DEFAULT_MODEL_ID = "noop" # fix @@ -49,6 +51,7 @@ def _solid_rgb_frame(width: int, height: int, rgb: tuple[int, int, int]) -> av.V async def main() -> None: + configure_logging() args = _parse_args() frame_interval = 1.0 / max(1e-6, args.fps) diff --git a/src/livepeer_gateway/__init__.py b/src/livepeer_gateway/__init__.py index 3a82a4d..ada3b9c 100644 --- a/src/livepeer_gateway/__init__.py +++ b/src/livepeer_gateway/__init__.py @@ -17,6 +17,8 @@ ) from .errors import LivepeerGatewayError, NoOrchestratorAvailableError, PaymentError from .events import Events +from .logging_config import apply_package_log_level, configure_logging + from .media_publish import ( AudioOutputConfig, MediaPublish, @@ -80,6 +82,7 @@ "ChannelReader", "JSONLReader", "JSONLWriter", + "configure_logging", "Events", "PaymentSession", "parse_token", @@ -99,3 +102,6 @@ "TrickleSubscriberStats", "VideoDecodedMediaFrame", ] + +apply_package_log_level() + diff --git a/src/livepeer_gateway/logging_config.py b/src/livepeer_gateway/logging_config.py new file mode 100644 index 0000000..3ddc459 --- /dev/null +++ b/src/livepeer_gateway/logging_config.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +import logging +import os + + +_PACKAGE_LOGGER = "livepeer_gateway" +_DEFAULT_LEVEL = logging.INFO +_LOG_FORMAT = "%(levelname)s %(name)s: %(message)s" + + +def _resolve_level(level: str | int | None = None) -> int: + if level is None: + level = os.environ.get("LOG_LEVEL", "INFO") + if isinstance(level, int): + return level + return getattr(logging, str(level).upper(), _DEFAULT_LEVEL) + + +def apply_package_log_level(level: str | int | None = None) -> None: + """Set the livepeer_gateway logger level from arg or LOG_LEVEL env (default INFO).""" + logging.getLogger(_PACKAGE_LOGGER).setLevel(_resolve_level(level)) + + +def configure_logging(level: str | int | None = None) -> None: + """Configure livepeer_gateway log level from arg or LOG_LEVEL env (default INFO). + + Ensures a basic root handler exists so package logs are visible. + """ + resolved = _resolve_level(level) + apply_package_log_level(resolved) + if not logging.getLogger().handlers: + logging.basicConfig(level=resolved, format=_LOG_FORMAT) From aeab7ed997c2c033c4118cf6a33f8c2f0aee0c5b Mon Sep 17 00:00:00 2001 From: John | Elite Encoder Date: Tue, 14 Jul 2026 20:46:51 -0400 Subject: [PATCH 2/2] refactor: configure logging on package import Call configure_logging() from package __init__ so LOG_LEVEL works without per-example setup. Revert write_frames to rely on import-time config. --- examples/write_frames.py | 3 --- src/livepeer_gateway/__init__.py | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/write_frames.py b/examples/write_frames.py index 3614413..05b33ef 100644 --- a/examples/write_frames.py +++ b/examples/write_frames.py @@ -4,12 +4,10 @@ import av -from livepeer_gateway import configure_logging from livepeer_gateway.errors import LivepeerGatewayError from livepeer_gateway.lv2v import StartJobRequest, start_lv2v from livepeer_gateway.media_publish import MediaPublishConfig, VideoOutputConfig - DEFAULT_MODEL_ID = "noop" # fix @@ -51,7 +49,6 @@ def _solid_rgb_frame(width: int, height: int, rgb: tuple[int, int, int]) -> av.V async def main() -> None: - configure_logging() args = _parse_args() frame_interval = 1.0 / max(1e-6, args.fps) diff --git a/src/livepeer_gateway/__init__.py b/src/livepeer_gateway/__init__.py index ada3b9c..269479e 100644 --- a/src/livepeer_gateway/__init__.py +++ b/src/livepeer_gateway/__init__.py @@ -17,7 +17,7 @@ ) from .errors import LivepeerGatewayError, NoOrchestratorAvailableError, PaymentError from .events import Events -from .logging_config import apply_package_log_level, configure_logging +from .logging_config import configure_logging from .media_publish import ( AudioOutputConfig, @@ -103,5 +103,6 @@ "VideoDecodedMediaFrame", ] -apply_package_log_level() +# Honor LOG_LEVEL; add a root handler only if the app has not configured logging. +configure_logging()