Repository: getsentry/sentry-python

Issue:
SDK should not include `sentry-trace` header in outgoing requests to Sentry
The SDK HTTP client integration should treat requests made by the SDK itself different than other uses of the same HTTP client.

See the last line in:

```
(e) ~/s/sentry-python ❯❯❯ ipython                                      master ◼
Python 3.9.7 (default, Oct 13 2021, 06:45:31)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.29.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sentry_sdk

In [2]: sentry_sdk.init("https://d655584d05f14c58b86e9034aab6817f@o447951.ingest
   ...: .sentry.io/5461230", traces_sample_rate=1.0, debug=True)
 [sentry] DEBUG: Setting up integrations (with default = True)
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.django.DjangoIntegration: Django not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.flask.FlaskIntegration: Flask is not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.bottle.BottleIntegration: Bottle not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.falcon.FalconIntegration: Falcon not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.sanic.SanicIntegration: Sanic not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.celery.CeleryIntegration: Celery not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.rq.RqIntegration: RQ not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.aiohttp.AioHttpIntegration: AIOHTTP not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.tornado.TornadoIntegration: Tornado not installed
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.sqlalchemy.SqlalchemyIntegration: SQLAlchemy not installed.
 [sentry] DEBUG: Did not import default integration sentry_sdk.integrations.boto3.Boto3Integration: botocore is not installed
 [sentry] DEBUG: Setting up previously not enabled integration logging
 [sentry] DEBUG: Setting up previously not enabled integration stdlib
 [sentry] DEBUG: Setting up previously not enabled integration excepthook
 [sentry] DEBUG: Setting up previously not enabled integration dedupe
 [sentry] DEBUG: Setting up previously not enabled integration atexit
 [sentry] DEBUG: Setting up previously not enabled integration modules
 [sentry] DEBUG: Setting up previously not enabled integration argv
 [sentry] DEBUG: Setting up previously not enabled integration threading
 [sentry] DEBUG: Enabling integration logging
 [sentry] DEBUG: Enabling integration stdlib
 [sentry] DEBUG: Enabling integration excepthook
 [sentry] DEBUG: Enabling integration dedupe
 [sentry] DEBUG: Enabling integration atexit
 [sentry] DEBUG: Enabling integration modules
 [sentry] DEBUG: Enabling integration argv
 [sentry] DEBUG: Enabling integration threading
Out[2]: <sentry_sdk.hub._InitGuard at 0x10c6e8610>

In [3]: sentry_sdk.capture_message("hello")
Out[3]: '3d200219b7cf4a91ae83b6cbd2f49093'

 [sentry] DEBUG: Sending event, type:null level:info event_id:3d200219b7cf4a91ae83b6cbd2f49093 project:5461230 host:o447951.ingest.sentry.io
In [4]:  [sentry] DEBUG: [Tracing] Adding `sentry-trace` header 98b5922a479e409ebd9b30453c49ef26-b6e3874f16b788d2- to outgoing request to https://o447951.ingest.sentry.io/api/5461230/store/.
```

There should not be trace propagation happening in that case.


Discussion:

Resolving patch:
diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py
--- a/sentry_sdk/tracing_utils.py
+++ b/sentry_sdk/tracing_utils.py
@@ -374,6 +374,15 @@ def should_propagate_trace(hub, url):
     client = hub.client  # type: Any
     trace_propagation_targets = client.options["trace_propagation_targets"]
 
+    if client.transport and client.transport.parsed_dsn:
+        dsn_url = client.transport.parsed_dsn.netloc
+    else:
+        dsn_url = None
+
+    is_request_to_sentry = dsn_url and dsn_url in url
+    if is_request_to_sentry:
+        return False
+
     return match_regex_list(url, trace_propagation_targets, substring_matching=True)
 
 


Test patch:
diff --git a/tests/tracing/test_misc.py b/tests/tracing/test_misc.py
--- a/tests/tracing/test_misc.py
+++ b/tests/tracing/test_misc.py
@@ -8,6 +8,7 @@
 from sentry_sdk.consts import MATCH_ALL
 from sentry_sdk.tracing import Span, Transaction
 from sentry_sdk.tracing_utils import should_propagate_trace
+from sentry_sdk.utils import Dsn
 
 try:
     from unittest import mock  # python 3.3 and above
@@ -305,5 +306,50 @@ def test_should_propagate_trace(
     hub = MagicMock()
     hub.client = MagicMock()
     hub.client.options = {"trace_propagation_targets": trace_propagation_targets}
+    hub.client.transport = MagicMock()
+    hub.client.transport.parsed_dsn = Dsn("https://bla@xxx.sentry.io/12312012")
 
     assert should_propagate_trace(hub, url) == expected_propagation_decision
+
+
+@pytest.mark.parametrize(
+    "dsn,url,expected_propagation_decision",
+    [
+        (
+            "https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
+            "http://example.com",
+            True,
+        ),
+        (
+            "https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
+            "https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
+            False,
+        ),
+        (
+            "https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
+            "http://squirrelchasers.ingest.sentry.io/12312012",
+            False,
+        ),
+        (
+            "https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
+            "http://ingest.sentry.io/12312012",
+            True,
+        ),
+        (
+            "https://abc@localsentry.example.com/12312012",
+            "http://localsentry.example.com",
+            False,
+        ),
+    ],
+)
+def test_should_propagate_trace_to_sentry(
+    sentry_init, dsn, url, expected_propagation_decision
+):
+    sentry_init(
+        dsn=dsn,
+        traces_sample_rate=1.0,
+    )
+
+    Hub.current.client.transport.parsed_dsn = Dsn(dsn)
+
+    assert should_propagate_trace(Hub.current, url) == expected_propagation_decision