atexit.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import os
  2. import sys
  3. import atexit
  4. import sentry_sdk
  5. from sentry_sdk.utils import logger
  6. from sentry_sdk.integrations import Integration
  7. from typing import TYPE_CHECKING
  8. if TYPE_CHECKING:
  9. from typing import Any
  10. from typing import Optional
  11. def default_callback(pending, timeout):
  12. # type: (int, int) -> None
  13. """This is the default shutdown callback that is set on the options.
  14. It prints out a message to stderr that informs the user that some events
  15. are still pending and the process is waiting for them to flush out.
  16. """
  17. def echo(msg):
  18. # type: (str) -> None
  19. sys.stderr.write(msg + "\n")
  20. echo("Sentry is attempting to send %i pending events" % pending)
  21. echo("Waiting up to %s seconds" % timeout)
  22. echo("Press Ctrl-%s to quit" % (os.name == "nt" and "Break" or "C"))
  23. sys.stderr.flush()
  24. class AtexitIntegration(Integration):
  25. identifier = "atexit"
  26. def __init__(self, callback=None):
  27. # type: (Optional[Any]) -> None
  28. if callback is None:
  29. callback = default_callback
  30. self.callback = callback
  31. @staticmethod
  32. def setup_once():
  33. # type: () -> None
  34. @atexit.register
  35. def _shutdown():
  36. # type: () -> None
  37. client = sentry_sdk.get_client()
  38. integration = client.get_integration(AtexitIntegration)
  39. if integration is None:
  40. return
  41. logger.debug("atexit: got shutdown signal")
  42. logger.debug("atexit: shutting down client")
  43. sentry_sdk.get_isolation_scope().end_session()
  44. client.close(callback=integration.callback)