2525)
2626from sentry_sdk .serializer import serialize
2727from sentry_sdk .tracing import trace
28- from sentry_sdk .transport import BaseHttpTransport , make_transport
28+ from sentry_sdk .transport import HttpTransportCore , make_transport , AsyncHttpTransport
2929from sentry_sdk .consts import (
3030 SPANDATA ,
3131 DEFAULT_MAX_VALUE_LENGTH ,
@@ -214,6 +214,12 @@ def close(self, *args: Any, **kwargs: Any) -> None:
214214 def flush (self , * args : Any , ** kwargs : Any ) -> None :
215215 return None
216216
217+ async def close_async (self , * args : Any , ** kwargs : Any ) -> None :
218+ return None
219+
220+ async def flush_async (self , * args : Any , ** kwargs : Any ) -> None :
221+ return None
222+
217223 def __enter__ (self ) -> BaseClient :
218224 return self
219225
@@ -406,7 +412,7 @@ def _capture_envelope(envelope: Envelope) -> None:
406412 self .monitor
407413 or self .log_batcher
408414 or has_profiling_enabled (self .options )
409- or isinstance (self .transport , BaseHttpTransport )
415+ or isinstance (self .transport , HttpTransportCore )
410416 ):
411417 # If we have anything on that could spawn a background thread, we
412418 # need to check if it's safe to use them.
@@ -918,6 +924,14 @@ def get_integration(
918924
919925 return self .integrations .get (integration_name )
920926
927+ def _close_components (self ) -> None :
928+ """Kill all client components in the correct order."""
929+ self .session_flusher .kill ()
930+ if self .log_batcher is not None :
931+ self .log_batcher .kill ()
932+ if self .monitor :
933+ self .monitor .kill ()
934+
921935 def close (
922936 self ,
923937 timeout : Optional [float ] = None ,
@@ -928,19 +942,43 @@ def close(
928942 semantics as :py:meth:`Client.flush`.
929943 """
930944 if self .transport is not None :
945+ if isinstance (self .transport , AsyncHttpTransport ) and hasattr (
946+ self .transport , "loop"
947+ ):
948+ logger .debug (
949+ "close() used with AsyncHttpTransport, aborting. Please use close_async() instead."
950+ )
951+ return
931952 self .flush (timeout = timeout , callback = callback )
932-
933- self .session_flusher .kill ()
934-
935- if self .log_batcher is not None :
936- self .log_batcher .kill ()
937-
938- if self .monitor :
939- self .monitor .kill ()
940-
953+ self ._close_components ()
941954 self .transport .kill ()
942955 self .transport = None
943956
957+ async def close_async (
958+ self ,
959+ timeout : Optional [float ] = None ,
960+ callback : Optional [Callable [[int , float ], None ]] = None ,
961+ ) -> None :
962+ """
963+ Asynchronously close the client and shut down the transport. Arguments have the same
964+ semantics as :py:meth:`Client.flush_async`.
965+ """
966+ if self .transport is not None :
967+ if not (
968+ isinstance (self .transport , AsyncHttpTransport )
969+ and hasattr (self .transport , "loop" )
970+ ):
971+ logger .debug (
972+ "close_async() used with non-async transport, aborting. Please use close() instead."
973+ )
974+ return
975+ await self .flush_async (timeout = timeout , callback = callback )
976+ self ._close_components ()
977+ kill_task = self .transport .kill () # type: ignore
978+ if kill_task is not None :
979+ await kill_task
980+ self .transport = None
981+
944982 def flush (
945983 self ,
946984 timeout : Optional [float ] = None ,
@@ -954,15 +992,52 @@ def flush(
954992 :param callback: Is invoked with the number of pending events and the configured timeout.
955993 """
956994 if self .transport is not None :
995+ if isinstance (self .transport , AsyncHttpTransport ) and hasattr (
996+ self .transport , "loop"
997+ ):
998+ logger .debug (
999+ "flush() used with AsyncHttpTransport, aborting. Please use flush_async() instead."
1000+ )
1001+ return
9571002 if timeout is None :
9581003 timeout = self .options ["shutdown_timeout" ]
959- self .session_flusher .flush ()
960-
961- if self .log_batcher is not None :
962- self .log_batcher .flush ()
1004+ self ._flush_components ()
9631005
9641006 self .transport .flush (timeout = timeout , callback = callback )
9651007
1008+ async def flush_async (
1009+ self ,
1010+ timeout : Optional [float ] = None ,
1011+ callback : Optional [Callable [[int , float ], None ]] = None ,
1012+ ) -> None :
1013+ """
1014+ Asynchronously wait for the current events to be sent.
1015+
1016+ :param timeout: Wait for at most `timeout` seconds. If no `timeout` is provided, the `shutdown_timeout` option value is used.
1017+
1018+ :param callback: Is invoked with the number of pending events and the configured timeout.
1019+ """
1020+ if self .transport is not None :
1021+ if not (
1022+ isinstance (self .transport , AsyncHttpTransport )
1023+ and hasattr (self .transport , "loop" )
1024+ ):
1025+ logger .debug (
1026+ "flush_async() used with non-async transport, aborting. Please use flush() instead."
1027+ )
1028+ return
1029+ if timeout is None :
1030+ timeout = self .options ["shutdown_timeout" ]
1031+ self ._flush_components ()
1032+ flush_task = self .transport .flush (timeout = timeout , callback = callback ) # type: ignore
1033+ if flush_task is not None :
1034+ await flush_task
1035+
1036+ def _flush_components (self ) -> None :
1037+ self .session_flusher .flush ()
1038+ if self .log_batcher is not None :
1039+ self .log_batcher .flush ()
1040+
9661041 def __enter__ (self ) -> _Client :
9671042 return self
9681043
0 commit comments