1- from abc import ABC , abstractmethod
21import asyncio
2+ import gzip
33import io
4+ import json
5+ import logging
46import os
5- import gzip
67import socket
78import ssl
89import time
910import warnings
10- from datetime import datetime , timedelta , timezone
11+ from abc import ABC , abstractmethod
1112from collections import defaultdict
13+ from datetime import datetime , timedelta , timezone
1214from urllib .request import getproxies
1315
1416try :
3537except ImportError :
3638 ASYNC_TRANSPORT_AVAILABLE = False
3739
38- import urllib3
40+ from typing import TYPE_CHECKING , Dict , List , cast
41+
3942import certifi
43+ import urllib3
4044
4145import sentry_sdk
4246from sentry_sdk .consts import EndpointType
47+ from sentry_sdk .envelope import Envelope , Item , PayloadRef
4348from sentry_sdk .utils import (
4449 Dsn ,
45- logger ,
4650 capture_internal_exceptions ,
51+ logger ,
4752 mark_sentry_task_internal ,
4853)
49- from sentry_sdk .worker import BackgroundWorker , Worker , AsyncWorker
50- from sentry_sdk .envelope import Envelope , Item , PayloadRef
51-
52- from typing import TYPE_CHECKING , cast , List , Dict
54+ from sentry_sdk .worker import AsyncWorker , BackgroundWorker , Worker
5355
5456if TYPE_CHECKING :
55- from typing import Any
56- from typing import Callable
57- from typing import DefaultDict
58- from typing import Iterable
59- from typing import Mapping
60- from typing import Optional
61- from typing import Self
62- from typing import Tuple
63- from typing import Type
64- from typing import Union
65-
66- from urllib3 .poolmanager import PoolManager
67- from urllib3 .poolmanager import ProxyManager
57+ from typing import (
58+ Any ,
59+ Callable ,
60+ DefaultDict ,
61+ Iterable ,
62+ Mapping ,
63+ Optional ,
64+ Self ,
65+ Tuple ,
66+ Type ,
67+ Union ,
68+ )
69+
70+ from urllib3 .poolmanager import PoolManager , ProxyManager
6871
6972 from sentry_sdk ._types import Event , EventDataCategory
7073
@@ -1081,6 +1084,83 @@ def _make_pool(
10811084 return httpcore .ConnectionPool (** opts )
10821085
10831086
1087+ class _EnvelopePrinterTransport (Transport ):
1088+ """Wraps another transport, printing envelope contents to the SDK debug logger before sending."""
1089+
1090+ def __init__ (self , transport : "Transport" ) -> None :
1091+ Transport .__init__ (self , options = transport .options )
1092+ self ._inner = transport
1093+ self .parsed_dsn = transport .parsed_dsn
1094+
1095+ self .envelope_logger = logging .getLogger ("sentry_sdk.envelopes" )
1096+ self .envelope_logger .setLevel (logging .INFO )
1097+ self .envelope_logger .propagate = False
1098+ if not self .envelope_logger .handlers :
1099+ handler = logging .StreamHandler ()
1100+ handler .setLevel (logging .INFO )
1101+ handler .setFormatter (logging .Formatter ("%(message)s" ))
1102+ self .envelope_logger .addHandler (handler )
1103+
1104+ @property # type: ignore[misc]
1105+ def __class__ (self ) -> type :
1106+ return self ._inner .__class__
1107+
1108+ def capture_envelope (self , envelope : "Envelope" ) -> None :
1109+ try :
1110+ self .envelope_logger .info ("--- Sentry Envelope ---" )
1111+ self .envelope_logger .info (
1112+ "Headers: %s" , json .dumps (envelope .headers , indent = 2 , default = str )
1113+ )
1114+ for item in envelope .items :
1115+ self .envelope_logger .info (" Item type: %s" , item .type )
1116+ self .envelope_logger .info (
1117+ " Item headers: %s" ,
1118+ json .dumps (item .headers , indent = 2 , default = str ),
1119+ )
1120+ try :
1121+ payload = json .loads (item .get_bytes ())
1122+ self .envelope_logger .info (
1123+ " Payload:\n %s" ,
1124+ json .dumps (payload , indent = 2 , default = str ),
1125+ )
1126+ except (ValueError , TypeError ):
1127+ self .envelope_logger .info (
1128+ " Payload: <binary %d bytes>" ,
1129+ len (item .get_bytes ()),
1130+ )
1131+ self .envelope_logger .info ("--- End Envelope ---" )
1132+ except Exception :
1133+ pass
1134+
1135+ self ._inner .capture_envelope (envelope )
1136+
1137+ def flush (
1138+ self ,
1139+ timeout : float ,
1140+ callback : "Optional[Any]" = None ,
1141+ ) -> "Any" :
1142+ return self ._inner .flush (timeout , callback )
1143+
1144+ def kill (self ) -> "Any" :
1145+ return self ._inner .kill ()
1146+
1147+ def record_lost_event (
1148+ self ,
1149+ reason : str ,
1150+ data_category : "Optional[EventDataCategory]" = None ,
1151+ item : "Optional[Item]" = None ,
1152+ * ,
1153+ quantity : int = 1 ,
1154+ ) -> None :
1155+ self ._inner .record_lost_event (reason , data_category , item , quantity = quantity )
1156+
1157+ def is_healthy (self ) -> bool :
1158+ return self ._inner .is_healthy ()
1159+
1160+ def __getattr__ (self , name : str ) -> "Any" :
1161+ return getattr (self ._inner , name )
1162+
1163+
10841164class _FunctionTransport (Transport ):
10851165 """
10861166 DEPRECATED: Users wishing to provide a custom transport should subclass
@@ -1147,8 +1227,10 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]":
11471227 "You tried to use AsyncHttpTransport but don't have httpcore[asyncio] installed. Falling back to sync transport."
11481228 )
11491229
1230+ transport : "Optional[Transport]" = None
1231+
11501232 if isinstance (ref_transport , Transport ):
1151- return ref_transport
1233+ transport = ref_transport
11521234 elif isinstance (ref_transport , type ) and issubclass (ref_transport , Transport ):
11531235 transport_cls = ref_transport
11541236 elif callable (ref_transport ):
@@ -1158,11 +1240,16 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]":
11581240 DeprecationWarning ,
11591241 stacklevel = 2 ,
11601242 )
1161- return _FunctionTransport (ref_transport )
1243+ transport = _FunctionTransport (ref_transport )
11621244
11631245 # if a transport class is given only instantiate it if the dsn is not
11641246 # empty or None
1165- if options ["dsn" ]:
1166- return transport_cls (options )
1247+ if transport is None and options ["dsn" ]:
1248+ transport = transport_cls (options )
1249+
1250+ if transport is not None and os .environ .get (
1251+ "SENTRY_PRINT_ENVELOPES" , ""
1252+ ).lower () in ("1" , "true" , "yes" ):
1253+ transport = _EnvelopePrinterTransport (transport )
11671254
1168- return None
1255+ return transport
0 commit comments