25
25
)
26
26
from sentry_sdk .serializer import serialize
27
27
from sentry_sdk .tracing import trace
28
- from sentry_sdk .transport import BaseHttpTransport , make_transport
28
+ from sentry_sdk .transport import HttpTransportCore , make_transport , AsyncHttpTransport
29
29
from sentry_sdk .consts import (
30
30
SPANDATA ,
31
31
DEFAULT_MAX_VALUE_LENGTH ,
@@ -214,6 +214,12 @@ def close(self, *args: Any, **kwargs: Any) -> None:
214
214
def flush (self , * args : Any , ** kwargs : Any ) -> None :
215
215
return None
216
216
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
+
217
223
def __enter__ (self ) -> BaseClient :
218
224
return self
219
225
@@ -406,7 +412,7 @@ def _capture_envelope(envelope: Envelope) -> None:
406
412
self .monitor
407
413
or self .log_batcher
408
414
or has_profiling_enabled (self .options )
409
- or isinstance (self .transport , BaseHttpTransport )
415
+ or isinstance (self .transport , HttpTransportCore )
410
416
):
411
417
# If we have anything on that could spawn a background thread, we
412
418
# need to check if it's safe to use them.
@@ -918,6 +924,14 @@ def get_integration(
918
924
919
925
return self .integrations .get (integration_name )
920
926
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
+
921
935
def close (
922
936
self ,
923
937
timeout : Optional [float ] = None ,
@@ -928,19 +942,43 @@ def close(
928
942
semantics as :py:meth:`Client.flush`.
929
943
"""
930
944
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
931
952
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 ()
941
954
self .transport .kill ()
942
955
self .transport = None
943
956
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
+
944
982
def flush (
945
983
self ,
946
984
timeout : Optional [float ] = None ,
@@ -954,15 +992,52 @@ def flush(
954
992
:param callback: Is invoked with the number of pending events and the configured timeout.
955
993
"""
956
994
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
957
1002
if timeout is None :
958
1003
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 ()
963
1005
964
1006
self .transport .flush (timeout = timeout , callback = callback )
965
1007
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
+
966
1041
def __enter__ (self ) -> _Client :
967
1042
return self
968
1043
0 commit comments