From ba9db5d5516289a32e0ea63ad0ee1b9188595749 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Fri, 1 May 2026 10:38:36 -0400 Subject: [PATCH 1/6] feat(transport): Add EnvelopePrinterTransport for debug logging Add a decorator transport that logs envelope contents via the SDK debug logger before forwarding to the inner transport. Activated by setting SENTRY_PRINT_ENVELOPES=1|true|yes. Includes tests for delegation, logging behavior, make_transport integration, and strict env var parsing. Co-Authored-By: Claude Opus 4.6 --- sentry_sdk/transport.py | 67 +++++++++- tests/test_transport.py | 268 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 334 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py index 1bdc7c6a7d..1e64333b1d 100644 --- a/sentry_sdk/transport.py +++ b/sentry_sdk/transport.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod import asyncio import io +import json import os import gzip import socket @@ -1081,6 +1082,65 @@ def _make_pool( return httpcore.ConnectionPool(**opts) +class EnvelopePrinterTransport(Transport): + """Wraps another transport, printing envelope contents to the SDK debug logger before sending.""" + + def __init__(self, transport: "Transport") -> None: + Transport.__init__(self, options=transport.options) + self._inner = transport + self.parsed_dsn = transport.parsed_dsn + + def capture_envelope(self, envelope: "Envelope") -> None: + try: + logger.debug("--- Sentry Envelope ---") + logger.debug("Headers: %s", json.dumps(envelope.headers, default=str)) + for item in envelope.items: + logger.debug(" Item type: %s", item.type) + logger.debug( + " Item headers: %s", + json.dumps(item.headers, default=str), + ) + try: + payload = json.loads(item.get_bytes()) + logger.debug( + " Payload:\n%s", + json.dumps(payload, indent=2, default=str), + ) + except (ValueError, TypeError): + logger.debug( + " Payload: ", + len(item.get_bytes()), + ) + logger.debug("--- End Envelope ---") + except Exception: + pass + + self._inner.capture_envelope(envelope) + + def flush( + self, + timeout: float, + callback: "Optional[Any]" = None, + ) -> None: + self._inner.flush(timeout, callback) + + def kill(self) -> None: + self._inner.kill() + + def record_lost_event( + self, + reason: str, + data_category: "Optional[EventDataCategory]" = None, + item: "Optional[Item]" = None, + *, + quantity: int = 1, + ) -> None: + self._inner.record_lost_event(reason, data_category, item, quantity=quantity) + + def is_healthy(self) -> bool: + return self._inner.is_healthy() + + class _FunctionTransport(Transport): """ DEPRECATED: Users wishing to provide a custom transport should subclass @@ -1163,6 +1223,11 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]": # if a transport class is given only instantiate it if the dsn is not # empty or None if options["dsn"]: - return transport_cls(options) + transport = transport_cls(options) + + if os.environ.get("SENTRY_PRINT_ENVELOPES", "").lower() in ("1", "true", "yes"): + transport = EnvelopePrinterTransport(transport) + + return transport return None diff --git a/tests/test_transport.py b/tests/test_transport.py index a121d3f1be..30e104b065 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -37,12 +37,16 @@ Hub, ) from sentry_sdk._compat import PY37, PY38 +from sentry_sdk.utils import Dsn from sentry_sdk.envelope import Envelope, Item, parse_json, PayloadRef from sentry_sdk.transport import ( KEEP_ALIVE_SOCKET_OPTIONS, + EnvelopePrinterTransport, + Transport, _parse_rate_limits, AsyncHttpTransport, HttpTransport, + make_transport, ) from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger from sentry_sdk.integrations.asyncio import AsyncioIntegration @@ -1041,3 +1045,267 @@ async def send_message(i): # New request should be dropped due to rate limiting assert len(capturing_server.captured) == 0 await client.close_async(timeout=2.0) + + +# --- EnvelopePrinterTransport tests --- + + +class FakeTransport(Transport): + def __init__(self): + self.options = {"dsn": "https://foo@sentry.io/123"} + self.parsed_dsn = Dsn("https://foo@sentry.io/123") + self.captured_envelopes = [] + self.flushed = [] + self.killed = False + self.lost_events = [] + self._healthy = True + + def capture_envelope(self, envelope): + self.captured_envelopes.append(envelope) + + def flush(self, timeout, callback=None): + self.flushed.append((timeout, callback)) + + def kill(self): + self.killed = True + + def record_lost_event(self, reason, data_category=None, item=None, *, quantity=1): + self.lost_events.append((reason, data_category, item, quantity)) + + def is_healthy(self): + return self._healthy + + +def _make_json_envelope(): + envelope = Envelope(headers={"event_id": "abc123"}) + envelope.add_item(Item(payload='{"message": "hello"}', type="event")) + return envelope + + +def _make_binary_envelope(): + envelope = Envelope(headers={"event_id": "bin456"}) + envelope.add_item(Item(payload=b"\x00\x01\x02\x03", type="attachment")) + return envelope + + +class TestEnvelopePrinterTransportDelegation: + def test_capture_envelope_delegates(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = _make_json_envelope() + + transport.capture_envelope(envelope) + + assert inner.captured_envelopes == [envelope] + + def test_flush_delegates(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + cb = lambda: None + + transport.flush(10.0, cb) + + assert inner.flushed == [(10.0, cb)] + + def test_kill_delegates(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + + transport.kill() + + assert inner.killed is True + + def test_record_lost_event_delegates(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + item = Item(payload='{"x": 1}', type="event") + + transport.record_lost_event("queue_overflow", "error", item, quantity=5) + + assert inner.lost_events == [("queue_overflow", "error", item, 5)] + + def test_is_healthy_delegates(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + + assert transport.is_healthy() is True + + inner._healthy = False + assert transport.is_healthy() is False + + def test_parsed_dsn_forwarded(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + + assert transport.parsed_dsn is inner.parsed_dsn + + +def _collect_debug_log_text(mock_debug): + parts = [] + for call in mock_debug.call_args_list: + args = call[0] + if len(args) == 1: + parts.append(args[0]) + else: + parts.append(args[0] % args[1:]) + return "\n".join(parts) + + +class TestEnvelopePrinterTransportLogging: + def test_json_payload_is_pretty_printed(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = _make_json_envelope() + + with mock.patch("sentry_sdk.transport.logger") as mock_logger: + transport.capture_envelope(envelope) + + log_text = _collect_debug_log_text(mock_logger.debug) + assert '"message": "hello"' in log_text + + def test_binary_payload_shows_byte_count(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = _make_binary_envelope() + + with mock.patch("sentry_sdk.transport.logger") as mock_logger: + transport.capture_envelope(envelope) + + log_text = _collect_debug_log_text(mock_logger.debug) + assert "" in log_text + + def test_envelope_headers_are_logged(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = _make_json_envelope() + + with mock.patch("sentry_sdk.transport.logger") as mock_logger: + transport.capture_envelope(envelope) + + log_text = _collect_debug_log_text(mock_logger.debug) + assert "abc123" in log_text + + def test_item_type_and_headers_are_logged(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = _make_json_envelope() + + with mock.patch("sentry_sdk.transport.logger") as mock_logger: + transport.capture_envelope(envelope) + + log_text = _collect_debug_log_text(mock_logger.debug) + assert "Item type:" in log_text + assert "event" in log_text + assert "Item headers:" in log_text + + def test_logging_exception_does_not_propagate(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = _make_json_envelope() + + with mock.patch( + "sentry_sdk.transport.json.dumps", side_effect=RuntimeError("boom") + ): + transport.capture_envelope(envelope) + + assert inner.captured_envelopes == [envelope] + + def test_empty_envelope_logs_headers_only(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = Envelope(headers={"event_id": "empty1"}) + + with mock.patch("sentry_sdk.transport.logger") as mock_logger: + transport.capture_envelope(envelope) + + log_text = _collect_debug_log_text(mock_logger.debug) + assert "empty1" in log_text + assert "Item type:" not in log_text + assert inner.captured_envelopes == [envelope] + + def test_multiple_items_each_logged(self): + inner = FakeTransport() + transport = EnvelopePrinterTransport(inner) + envelope = Envelope(headers={"event_id": "multi"}) + envelope.add_item(Item(payload='{"a": 1}', type="event")) + envelope.add_item(Item(payload=b"\xff", type="attachment")) + + with mock.patch("sentry_sdk.transport.logger") as mock_logger: + transport.capture_envelope(envelope) + + log_text = _collect_debug_log_text(mock_logger.debug) + assert '"a": 1' in log_text + assert "" in log_text + + +class TestMakeTransportEnvelopePrinter: + def test_env_var_wraps_transport(self): + options = { + "dsn": "https://foo@sentry.io/123", + "transport": None, + "_experiments": {}, + "integrations": [], + "send_client_reports": True, + "transport_queue_size": 100, + "keep_alive": False, + "socket_options": None, + "ca_certs": None, + "cert_file": None, + "key_file": None, + "http_proxy": None, + "https_proxy": None, + "proxy_headers": None, + } + with mock.patch.dict(os.environ, {"SENTRY_PRINT_ENVELOPES": "1"}): + transport = make_transport(options) + + assert isinstance(transport, EnvelopePrinterTransport) + assert isinstance(transport._inner, HttpTransport) + + def test_no_env_var_returns_plain_transport(self): + options = { + "dsn": "https://foo@sentry.io/123", + "transport": None, + "_experiments": {}, + "integrations": [], + "send_client_reports": True, + "transport_queue_size": 100, + "keep_alive": False, + "socket_options": None, + "ca_certs": None, + "cert_file": None, + "key_file": None, + "http_proxy": None, + "https_proxy": None, + "proxy_headers": None, + } + with mock.patch.dict(os.environ, {}, clear=False): + os.environ.pop("SENTRY_PRINT_ENVELOPES", None) + transport = make_transport(options) + + assert isinstance(transport, HttpTransport) + assert not isinstance(transport, EnvelopePrinterTransport) + + @pytest.mark.parametrize("value", ["0", "false", "no", ""]) + def test_falsy_env_var_values_do_not_wrap(self, value): + options = { + "dsn": "https://foo@sentry.io/123", + "transport": None, + "_experiments": {}, + "integrations": [], + "send_client_reports": True, + "transport_queue_size": 100, + "keep_alive": False, + "socket_options": None, + "ca_certs": None, + "cert_file": None, + "key_file": None, + "http_proxy": None, + "https_proxy": None, + "proxy_headers": None, + } + with mock.patch.dict(os.environ, {"SENTRY_PRINT_ENVELOPES": value}): + transport = make_transport(options) + + assert isinstance(transport, HttpTransport) + assert not isinstance(transport, EnvelopePrinterTransport) From e7b516142b1c660ab1ccf5e7d66a79871f879bdf Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Fri, 1 May 2026 12:27:21 -0400 Subject: [PATCH 2/6] Add indentation to headers --- sentry_sdk/transport.py | 49 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py index 1e64333b1d..a72dad6558 100644 --- a/sentry_sdk/transport.py +++ b/sentry_sdk/transport.py @@ -1,15 +1,15 @@ -from abc import ABC, abstractmethod import asyncio +import gzip import io import json import os -import gzip import socket import ssl import time import warnings -from datetime import datetime, timedelta, timezone +from abc import ABC, abstractmethod from collections import defaultdict +from datetime import datetime, timedelta, timezone from urllib.request import getproxies try: @@ -36,36 +36,37 @@ except ImportError: ASYNC_TRANSPORT_AVAILABLE = False -import urllib3 +from typing import TYPE_CHECKING, Dict, List, cast + import certifi +import urllib3 import sentry_sdk from sentry_sdk.consts import EndpointType +from sentry_sdk.envelope import Envelope, Item, PayloadRef from sentry_sdk.utils import ( Dsn, - logger, capture_internal_exceptions, + logger, mark_sentry_task_internal, ) -from sentry_sdk.worker import BackgroundWorker, Worker, AsyncWorker -from sentry_sdk.envelope import Envelope, Item, PayloadRef - -from typing import TYPE_CHECKING, cast, List, Dict +from sentry_sdk.worker import AsyncWorker, BackgroundWorker, Worker if TYPE_CHECKING: - from typing import Any - from typing import Callable - from typing import DefaultDict - from typing import Iterable - from typing import Mapping - from typing import Optional - from typing import Self - from typing import Tuple - from typing import Type - from typing import Union - - from urllib3.poolmanager import PoolManager - from urllib3.poolmanager import ProxyManager + from typing import ( + Any, + Callable, + DefaultDict, + Iterable, + Mapping, + Optional, + Self, + Tuple, + Type, + Union, + ) + + from urllib3.poolmanager import PoolManager, ProxyManager from sentry_sdk._types import Event, EventDataCategory @@ -1093,7 +1094,9 @@ def __init__(self, transport: "Transport") -> None: def capture_envelope(self, envelope: "Envelope") -> None: try: logger.debug("--- Sentry Envelope ---") - logger.debug("Headers: %s", json.dumps(envelope.headers, default=str)) + logger.debug( + "Headers: %s", json.dumps(envelope.headers, indent=2, default=str) + ) for item in envelope.items: logger.debug(" Item type: %s", item.type) logger.debug( From f050b854f849f2dce691a93d0f6f1837f203d979 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Fri, 1 May 2026 15:31:22 -0400 Subject: [PATCH 3/6] Fix EnvelopePrinterTransport isinstance, return values, and make_transport coverage - Override __class__ to delegate to inner transport so isinstance checks (e.g. AsyncHttpTransport) remain transparent - Add __getattr__ fallback for attributes not explicitly defined - Return values from flush() and kill() so async tasks propagate - Wrap transport in all make_transport paths (pre-instantiated, callable) Co-Authored-By: Claude Opus 4.6 --- sentry_sdk/transport.py | 33 ++++++++++++++-------- tests/test_transport.py | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py index a72dad6558..ab1a3fb9c8 100644 --- a/sentry_sdk/transport.py +++ b/sentry_sdk/transport.py @@ -1091,6 +1091,10 @@ def __init__(self, transport: "Transport") -> None: self._inner = transport self.parsed_dsn = transport.parsed_dsn + @property # type: ignore[misc] + def __class__(self) -> type: + return self._inner.__class__ + def capture_envelope(self, envelope: "Envelope") -> None: try: logger.debug("--- Sentry Envelope ---") @@ -1124,11 +1128,11 @@ def flush( self, timeout: float, callback: "Optional[Any]" = None, - ) -> None: - self._inner.flush(timeout, callback) + ) -> "Any": + return self._inner.flush(timeout, callback) - def kill(self) -> None: - self._inner.kill() + def kill(self) -> "Any": + return self._inner.kill() def record_lost_event( self, @@ -1143,6 +1147,9 @@ def record_lost_event( def is_healthy(self) -> bool: return self._inner.is_healthy() + def __getattr__(self, name: str) -> "Any": + return getattr(self._inner, name) + class _FunctionTransport(Transport): """ @@ -1210,8 +1217,10 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]": "You tried to use AsyncHttpTransport but don't have httpcore[asyncio] installed. Falling back to sync transport." ) + transport = None # type: Optional[Transport] + if isinstance(ref_transport, Transport): - return ref_transport + transport = ref_transport elif isinstance(ref_transport, type) and issubclass(ref_transport, Transport): transport_cls = ref_transport elif callable(ref_transport): @@ -1221,16 +1230,16 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]": DeprecationWarning, stacklevel=2, ) - return _FunctionTransport(ref_transport) + transport = _FunctionTransport(ref_transport) # if a transport class is given only instantiate it if the dsn is not # empty or None - if options["dsn"]: + if transport is None and options["dsn"]: transport = transport_cls(options) - if os.environ.get("SENTRY_PRINT_ENVELOPES", "").lower() in ("1", "true", "yes"): - transport = EnvelopePrinterTransport(transport) - - return transport + if transport is not None and os.environ.get( + "SENTRY_PRINT_ENVELOPES", "" + ).lower() in ("1", "true", "yes"): + transport = EnvelopePrinterTransport(transport) - return None + return transport diff --git a/tests/test_transport.py b/tests/test_transport.py index 30e104b065..bbf1cbf2be 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -1309,3 +1309,65 @@ def test_falsy_env_var_values_do_not_wrap(self, value): assert isinstance(transport, HttpTransport) assert not isinstance(transport, EnvelopePrinterTransport) + + def test_env_var_wraps_pre_instantiated_transport(self): + inner = FakeTransport() + options = { + "dsn": "https://foo@sentry.io/123", + "transport": inner, + "_experiments": {}, + "integrations": [], + "send_client_reports": True, + "transport_queue_size": 100, + "keep_alive": False, + "socket_options": None, + "ca_certs": None, + "cert_file": None, + "key_file": None, + "http_proxy": None, + "https_proxy": None, + "proxy_headers": None, + } + with mock.patch.dict(os.environ, {"SENTRY_PRINT_ENVELOPES": "1"}): + transport = make_transport(options) + + assert isinstance(transport, EnvelopePrinterTransport) + assert transport._inner is inner + + +class TestEnvelopePrinterTransportIsinstance: + def test_isinstance_matches_inner_transport_class(self): + inner = FakeTransport() + wrapper = EnvelopePrinterTransport(inner) + + assert isinstance(wrapper, FakeTransport) + assert isinstance(wrapper, Transport) + + def test_isinstance_matches_http_transport(self): + options = { + "dsn": "https://foo@sentry.io/123", + "transport": None, + "_experiments": {}, + "integrations": [], + "send_client_reports": True, + "transport_queue_size": 100, + "keep_alive": False, + "socket_options": None, + "ca_certs": None, + "cert_file": None, + "key_file": None, + "http_proxy": None, + "https_proxy": None, + "proxy_headers": None, + } + with mock.patch.dict(os.environ, {"SENTRY_PRINT_ENVELOPES": "1"}): + transport = make_transport(options) + + assert isinstance(transport, HttpTransport) + + def test_getattr_delegates_to_inner(self): + inner = FakeTransport() + inner.custom_attr = "test_value" + wrapper = EnvelopePrinterTransport(inner) + + assert wrapper.custom_attr == "test_value" From 4924648cef4f7d5fd516d6ccdc257d619ed4c357 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Fri, 1 May 2026 16:40:22 -0400 Subject: [PATCH 4/6] Make the transport private --- sentry_sdk/transport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py index ab1a3fb9c8..6dbf2ec89d 100644 --- a/sentry_sdk/transport.py +++ b/sentry_sdk/transport.py @@ -1105,7 +1105,7 @@ def capture_envelope(self, envelope: "Envelope") -> None: logger.debug(" Item type: %s", item.type) logger.debug( " Item headers: %s", - json.dumps(item.headers, default=str), + json.dumps(item.headers, indent=2, default=str), ) try: payload = json.loads(item.get_bytes()) From ab577dceff7a9530f03ebc5a0efb8d77a6685263 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Fri, 1 May 2026 16:44:43 -0400 Subject: [PATCH 5/6] forgot to save a file before commit and push --- sentry_sdk/transport.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/transport.py b/sentry_sdk/transport.py index 6dbf2ec89d..cf19f6d16b 100644 --- a/sentry_sdk/transport.py +++ b/sentry_sdk/transport.py @@ -1083,7 +1083,7 @@ def _make_pool( return httpcore.ConnectionPool(**opts) -class EnvelopePrinterTransport(Transport): +class _EnvelopePrinterTransport(Transport): """Wraps another transport, printing envelope contents to the SDK debug logger before sending.""" def __init__(self, transport: "Transport") -> None: @@ -1240,6 +1240,6 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]": if transport is not None and os.environ.get( "SENTRY_PRINT_ENVELOPES", "" ).lower() in ("1", "true", "yes"): - transport = EnvelopePrinterTransport(transport) + transport = _EnvelopePrinterTransport(transport) return transport From 239a332d685a7635d356d497334addc7c9418d37 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Fri, 1 May 2026 16:55:20 -0400 Subject: [PATCH 6/6] . --- tests/test_transport.py | 70 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/tests/test_transport.py b/tests/test_transport.py index bbf1cbf2be..774d6d78a7 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -1,14 +1,15 @@ +import asyncio import logging -import pickle import os +import pickle import socket import sys -import asyncio from collections import defaultdict from datetime import datetime, timedelta, timezone from unittest import mock import pytest + from tests.conftest import CapturingServer try: @@ -30,27 +31,26 @@ import sentry_sdk from sentry_sdk import ( Client, + Hub, add_breadcrumb, capture_message, - isolation_scope, get_isolation_scope, - Hub, + isolation_scope, ) from sentry_sdk._compat import PY37, PY38 -from sentry_sdk.utils import Dsn -from sentry_sdk.envelope import Envelope, Item, parse_json, PayloadRef +from sentry_sdk.envelope import Envelope, Item, PayloadRef, parse_json +from sentry_sdk.integrations.asyncio import AsyncioIntegration +from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger from sentry_sdk.transport import ( KEEP_ALIVE_SOCKET_OPTIONS, - EnvelopePrinterTransport, - Transport, - _parse_rate_limits, AsyncHttpTransport, HttpTransport, + Transport, + _EnvelopePrinterTransport, + _parse_rate_limits, make_transport, ) -from sentry_sdk.integrations.logging import LoggingIntegration, ignore_logger -from sentry_sdk.integrations.asyncio import AsyncioIntegration - +from sentry_sdk.utils import Dsn server = None @@ -1047,7 +1047,7 @@ async def send_message(i): await client.close_async(timeout=2.0) -# --- EnvelopePrinterTransport tests --- +# --- _EnvelopePrinterTransport tests --- class FakeTransport(Transport): @@ -1088,10 +1088,10 @@ def _make_binary_envelope(): return envelope -class TestEnvelopePrinterTransportDelegation: +class Test_EnvelopePrinterTransportDelegation: def test_capture_envelope_delegates(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = _make_json_envelope() transport.capture_envelope(envelope) @@ -1100,7 +1100,7 @@ def test_capture_envelope_delegates(self): def test_flush_delegates(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) cb = lambda: None transport.flush(10.0, cb) @@ -1109,7 +1109,7 @@ def test_flush_delegates(self): def test_kill_delegates(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) transport.kill() @@ -1117,7 +1117,7 @@ def test_kill_delegates(self): def test_record_lost_event_delegates(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) item = Item(payload='{"x": 1}', type="event") transport.record_lost_event("queue_overflow", "error", item, quantity=5) @@ -1126,7 +1126,7 @@ def test_record_lost_event_delegates(self): def test_is_healthy_delegates(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) assert transport.is_healthy() is True @@ -1135,7 +1135,7 @@ def test_is_healthy_delegates(self): def test_parsed_dsn_forwarded(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) assert transport.parsed_dsn is inner.parsed_dsn @@ -1151,10 +1151,10 @@ def _collect_debug_log_text(mock_debug): return "\n".join(parts) -class TestEnvelopePrinterTransportLogging: +class Test_EnvelopePrinterTransportLogging: def test_json_payload_is_pretty_printed(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = _make_json_envelope() with mock.patch("sentry_sdk.transport.logger") as mock_logger: @@ -1165,7 +1165,7 @@ def test_json_payload_is_pretty_printed(self): def test_binary_payload_shows_byte_count(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = _make_binary_envelope() with mock.patch("sentry_sdk.transport.logger") as mock_logger: @@ -1176,7 +1176,7 @@ def test_binary_payload_shows_byte_count(self): def test_envelope_headers_are_logged(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = _make_json_envelope() with mock.patch("sentry_sdk.transport.logger") as mock_logger: @@ -1187,7 +1187,7 @@ def test_envelope_headers_are_logged(self): def test_item_type_and_headers_are_logged(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = _make_json_envelope() with mock.patch("sentry_sdk.transport.logger") as mock_logger: @@ -1200,7 +1200,7 @@ def test_item_type_and_headers_are_logged(self): def test_logging_exception_does_not_propagate(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = _make_json_envelope() with mock.patch( @@ -1212,7 +1212,7 @@ def test_logging_exception_does_not_propagate(self): def test_empty_envelope_logs_headers_only(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = Envelope(headers={"event_id": "empty1"}) with mock.patch("sentry_sdk.transport.logger") as mock_logger: @@ -1225,7 +1225,7 @@ def test_empty_envelope_logs_headers_only(self): def test_multiple_items_each_logged(self): inner = FakeTransport() - transport = EnvelopePrinterTransport(inner) + transport = _EnvelopePrinterTransport(inner) envelope = Envelope(headers={"event_id": "multi"}) envelope.add_item(Item(payload='{"a": 1}', type="event")) envelope.add_item(Item(payload=b"\xff", type="attachment")) @@ -1259,7 +1259,7 @@ def test_env_var_wraps_transport(self): with mock.patch.dict(os.environ, {"SENTRY_PRINT_ENVELOPES": "1"}): transport = make_transport(options) - assert isinstance(transport, EnvelopePrinterTransport) + assert isinstance(transport, _EnvelopePrinterTransport) assert isinstance(transport._inner, HttpTransport) def test_no_env_var_returns_plain_transport(self): @@ -1284,7 +1284,7 @@ def test_no_env_var_returns_plain_transport(self): transport = make_transport(options) assert isinstance(transport, HttpTransport) - assert not isinstance(transport, EnvelopePrinterTransport) + assert not isinstance(transport, _EnvelopePrinterTransport) @pytest.mark.parametrize("value", ["0", "false", "no", ""]) def test_falsy_env_var_values_do_not_wrap(self, value): @@ -1308,7 +1308,7 @@ def test_falsy_env_var_values_do_not_wrap(self, value): transport = make_transport(options) assert isinstance(transport, HttpTransport) - assert not isinstance(transport, EnvelopePrinterTransport) + assert not isinstance(transport, _EnvelopePrinterTransport) def test_env_var_wraps_pre_instantiated_transport(self): inner = FakeTransport() @@ -1331,14 +1331,14 @@ def test_env_var_wraps_pre_instantiated_transport(self): with mock.patch.dict(os.environ, {"SENTRY_PRINT_ENVELOPES": "1"}): transport = make_transport(options) - assert isinstance(transport, EnvelopePrinterTransport) + assert isinstance(transport, _EnvelopePrinterTransport) assert transport._inner is inner -class TestEnvelopePrinterTransportIsinstance: +class Test_EnvelopePrinterTransportIsinstance: def test_isinstance_matches_inner_transport_class(self): inner = FakeTransport() - wrapper = EnvelopePrinterTransport(inner) + wrapper = _EnvelopePrinterTransport(inner) assert isinstance(wrapper, FakeTransport) assert isinstance(wrapper, Transport) @@ -1368,6 +1368,6 @@ def test_isinstance_matches_http_transport(self): def test_getattr_delegates_to_inner(self): inner = FakeTransport() inner.custom_attr = "test_value" - wrapper = EnvelopePrinterTransport(inner) + wrapper = _EnvelopePrinterTransport(inner) assert wrapper.custom_attr == "test_value"