From 4cbb47f6889de40dbe95b828516f56f26c9797f0 Mon Sep 17 00:00:00 2001 From: Daniil Gusev Date: Wed, 29 Oct 2025 16:40:26 +0100 Subject: [PATCH] Replace `twirp.context.Context` with a wrapper class to fix the logging issue --- getstream/video/rtc/connection_manager.py | 3 +- getstream/video/rtc/twirp_client_wrapper.py | 46 ++++++++++++++++++++- tests/test_twirp_client_wrapper.py | 3 +- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/getstream/video/rtc/connection_manager.py b/getstream/video/rtc/connection_manager.py index 0c326ba6..927d6603 100644 --- a/getstream/video/rtc/connection_manager.py +++ b/getstream/video/rtc/connection_manager.py @@ -6,7 +6,6 @@ import aioice import aiortc -from twirp.context import Context from getstream.common import telemetry from getstream.utils import StreamAsyncIOEventEmitter @@ -14,7 +13,7 @@ from getstream.video.rtc.pb.stream.video.sfu.event import events_pb2 from getstream.video.rtc.pb.stream.video.sfu.models import models_pb2 from getstream.video.rtc.pb.stream.video.sfu.signal_rpc import signal_pb2 -from getstream.video.rtc.twirp_client_wrapper import SfuRpcError, SignalClient +from getstream.video.rtc.twirp_client_wrapper import SfuRpcError, SignalClient, Context from getstream.video.async_call import Call from getstream.video.rtc.connection_utils import ( diff --git a/getstream/video/rtc/twirp_client_wrapper.py b/getstream/video/rtc/twirp_client_wrapper.py index bdec34eb..726e7f20 100644 --- a/getstream/video/rtc/twirp_client_wrapper.py +++ b/getstream/video/rtc/twirp_client_wrapper.py @@ -1,7 +1,12 @@ # -*- coding: utf-8 -*- -import logging -import functools import asyncio # Import asyncio if not already present +import functools +import logging + +import structlog +from structlog.stdlib import LoggerFactory, add_log_level +from structlog.types import BindableLogger +from twirp.context import Context as TwirpContext from getstream.common import telemetry from getstream.video.rtc.pb.stream.video.sfu.models import models_pb2 @@ -13,6 +18,42 @@ logger = logging.getLogger(__name__) +def _get_twirp_default_logger() -> BindableLogger: + """Re-generate the default structlog config used inside `twirp` without overriding + the root logger level. + A trimmed down copy of `twirp.logging.configure`""" + + structlog.configure( + logger_factory=LoggerFactory(), + processors=[ + add_log_level, + # Add timestamp + structlog.processors.TimeStamper("iso"), + # Add stack information + structlog.processors.StackInfoRenderer(), + # Set exception field using exec info + structlog.processors.format_exc_info, + # Render event_dict as JSON + structlog.processors.JSONRenderer(), + ], + ) + return structlog.get_logger() + + +_TWIRP_DEFAULT_LOGGER = _get_twirp_default_logger() + + +class Context(TwirpContext): + """A wrapper around `twirp.context.Context` to fix the logging issue. + Use it as a replacement. + """ + + def __init__(self, *args, headers=None): + # Passing our own logger here because twirp configures the root logger + # under the hood, making every other library noisy. + super().__init__(*args, logger=_TWIRP_DEFAULT_LOGGER, headers=headers) + + # Define a custom exception for SFU RPC errors class SfuRpcError(Exception): """Exception raised when an SFU RPC call returns an error.""" @@ -137,4 +178,5 @@ async def wrapped_method(*args, **kwargs): __all__ = [ "SfuRpcError", "SignalClient", + "Context", ] diff --git a/tests/test_twirp_client_wrapper.py b/tests/test_twirp_client_wrapper.py index be7fb614..911633ca 100644 --- a/tests/test_twirp_client_wrapper.py +++ b/tests/test_twirp_client_wrapper.py @@ -6,12 +6,11 @@ # import twirp.async_client # <-- REMOVE THIS DEBUG IMPORT # Modules to test -from getstream.video.rtc.twirp_client_wrapper import SignalClient, SfuRpcError +from getstream.video.rtc.twirp_client_wrapper import SignalClient, SfuRpcError, Context # Protobufs needed for requests/responses and error codes from getstream.video.rtc.pb.stream.video.sfu.signal_rpc import signal_pb2 from getstream.video.rtc.pb.stream.video.sfu.models import models_pb2 -from twirp.context import Context # No longer need to patch the base class path # ASYNC_CLIENT_PATH = "getstream.video.rtc.twirp_client_wrapper.AsyncSignalServerClient"