Repository: getsentry/sentry-python

Issue:
Add debug mode and do not use _internal_exceptions on expected fails
A debug mode should be added that logs out when events are dropped and internal exceptions are ignored.

Discussion:

Patch:
diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py
index 475cd478..6c9ae117 100644
--- a/sentry_sdk/consts.py
+++ b/sentry_sdk/consts.py
@@ -24,6 +24,7 @@ DEFAULT_OPTIONS = {
     "ignore_errors": [],
     "request_bodies": "medium",
     "before_send": None,
+    "debug": False,
 }
 
 SDK_INFO = {"name": "sentry-python", "version": VERSION}
diff --git a/sentry_sdk/hub.py b/sentry_sdk/hub.py
index ba2b4647..45881295 100644
--- a/sentry_sdk/hub.py
+++ b/sentry_sdk/hub.py
@@ -4,11 +4,13 @@ from contextlib import contextmanager
 
 from ._compat import with_metaclass
 from .scope import Scope
-from .utils import exc_info_from_error, event_from_exception, ContextVar
+from .utils import exc_info_from_error, event_from_exception, get_logger, ContextVar
 
 
 _local = ContextVar("sentry_current_hub")
 
+logger = get_logger(__name__)
+
 
 @contextmanager
 def _internal_exceptions():
@@ -134,7 +136,9 @@ class Hub(with_metaclass(HubMeta)):
     def capture_internal_exception(self, exc_info):
         """Capture an exception that is likely caused by a bug in the SDK
         itself."""
-        pass
+        client = self.client
+        if client is not None and client.options["debug"]:
+            logger.debug("Internal error in sentry_sdk", exc_info=exc_info)
 
     def add_breadcrumb(self, *args, **kwargs):
         """Adds a breadcrumb."""
diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py
index b5dbf6eb..eeb5e98b 100644
--- a/sentry_sdk/utils.py
+++ b/sentry_sdk/utils.py
@@ -1,6 +1,7 @@
 import os
 import sys
 import linecache
+import logging
 
 from datetime import datetime
 from collections import Mapping, Sequence
@@ -520,6 +521,14 @@ def strip_string(value, assume_length=None, max_length=512):
     return value[:max_length]
 
 
+def get_logger(name):
+    rv = logging.getLogger(name)
+    if not rv.handlers:
+        rv.addHandler(logging.StreamHandler(sys.stderr))
+        rv.setLevel(logging.DEBUG)
+    return rv
+
+
 try:
     from contextvars import ContextVar
 except ImportError:


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index a33aa855..b98a2c86 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -15,7 +15,10 @@ if not os.path.isfile(SEMAPHORE):
 
 
 @pytest.fixture(autouse=True)
-def reraise_internal_exceptions(monkeypatch):
+def reraise_internal_exceptions(request, monkeypatch):
+    if "tests_internal_exceptions" in request.keywords:
+        return
+
     def capture_internal_exception(exc_info):
         reraise(*exc_info)
 
diff --git a/tests/test_client.py b/tests/test_client.py
index dbf1cde4..d65f13c6 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -138,7 +138,7 @@ def test_configure_scope_unavailable(no_sdk, monkeypatch):
     assert not calls
 
 
-def test_transport_works(sentry_init, httpserver, request, capsys):
+def test_transport_works(httpserver, request, capsys):
     httpserver.serve_content("ok", 200)
 
     client = Client("http://foobar@{}/123".format(httpserver.url[len("http://") :]))
@@ -152,3 +152,21 @@ def test_transport_works(sentry_init, httpserver, request, capsys):
     out, err = capsys.readouterr()
     assert not err and not out
     assert httpserver.requests
+
+
+@pytest.mark.tests_internal_exceptions
+def test_client_debug_option_enabled(sentry_init, caplog):
+    sentry_init(debug=True)
+
+    Hub.current.capture_internal_exception((ValueError, ValueError("OK"), None))
+    assert "OK" in caplog.text
+
+
+@pytest.mark.tests_internal_exceptions
+@pytest.mark.parametrize("with_client", (True, False))
+def test_client_debug_option_disabled(with_client, sentry_init, caplog):
+    if with_client:
+        sentry_init()
+
+    Hub.current.capture_internal_exception((ValueError, ValueError("OK"), None))
+    assert "OK" not in caplog.text