Skip to content

Commit 88de844

Browse files
committed
Add org_id support
1 parent 2563650 commit 88de844

File tree

7 files changed

+66
-8
lines changed

7 files changed

+66
-8
lines changed

sentry_sdk/client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,13 @@ def _record_lost_event(
382382
_client_init_debug.set(self.options["debug"])
383383
self.transport = make_transport(self.options)
384384

385+
if (
386+
not self.options["org_id"]
387+
and self.transport
388+
and self.transport.parsed_dsn
389+
):
390+
self.options["org_id"] = self.transport.parsed_dsn.org_id
391+
385392
self.monitor = None
386393
if self.transport:
387394
if self.options["enable_backpressure_handling"]:

sentry_sdk/consts.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,7 @@ def __init__(
10231023
trace_ignore_status_codes=frozenset(), # type: AbstractSet[int]
10241024
enable_metrics=True, # type: bool
10251025
before_send_metric=None, # type: Optional[Callable[[Metric, Hint], Optional[Metric]]]
1026+
org_id=None, # type: Optional[str]
10261027
):
10271028
# type: (...) -> None
10281029
"""Initialize the Sentry SDK with the given parameters. All parameters described here can be used in a call to `sentry_sdk.init()`.
@@ -1426,6 +1427,10 @@ def __init__(
14261427
If `trace_ignore_status_codes` is not provided, requests with any status code
14271428
may be traced.
14281429
1430+
:param org_id: An optional organization ID. The SDK will try to extract if from the DSN in most cases
1431+
but you can provide it explicitly for self-hosted and Relay setups. This value is used for
1432+
trace propagation and for features like `strict_trace_continuation`.
1433+
14291434
:param _experiments:
14301435
"""
14311436
pass

sentry_sdk/tracing_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,8 @@ def from_options(cls, scope):
666666

667667
if client.parsed_dsn:
668668
sentry_items["public_key"] = client.parsed_dsn.public_key
669+
if client.parsed_dsn.org_id:
670+
sentry_items["org_id"] = client.parsed_dsn.org_id
669671

670672
if options.get("traces_sample_rate"):
671673
sentry_items["sample_rate"] = str(options["traces_sample_rate"])
@@ -698,6 +700,8 @@ def populate_from_transaction(cls, transaction):
698700

699701
if client.parsed_dsn:
700702
sentry_items["public_key"] = client.parsed_dsn.public_key
703+
if client.parsed_dsn.org_id:
704+
sentry_items["org_id"] = client.parsed_dsn.org_id
701705

702706
if (
703707
transaction.name

sentry_sdk/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ class BadDsn(ValueError):
294294
class Dsn:
295295
"""Represents a DSN."""
296296

297+
ORG_ID_REGEX = re.compile(r"^o(\d+)\.")
298+
297299
def __init__(self, value):
298300
# type: (Union[Dsn, str]) -> None
299301
if isinstance(value, Dsn):
@@ -310,6 +312,9 @@ def __init__(self, value):
310312

311313
self.host = parts.hostname
312314

315+
org_id_match = Dsn.ORG_ID_REGEX.match(self.host)
316+
self.org_id = org_id_match.group(1) if org_id_match else None # type: Optional[str]
317+
313318
if parts.port is None:
314319
self.port = self.scheme == "https" and 443 or 80 # type: int
315320
else:

tests/integrations/opentelemetry/test_span_processor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
SentrySpanProcessor,
1212
link_trace_context_to_error_event,
1313
)
14+
from sentry_sdk.utils import Dsn
1415
from sentry_sdk.tracing import Span, Transaction
1516
from sentry_sdk.tracing_utils import extract_sentrytrace_data
1617

@@ -23,7 +24,7 @@ def test_is_sentry_span():
2324

2425
client = MagicMock()
2526
client.options = {"instrumenter": "otel"}
26-
client.dsn = "https://[email protected]/123456"
27+
client.parsed_dsn = Dsn("https://[email protected]/123456")
2728
sentry_sdk.get_global_scope().set_client(client)
2829

2930
assert not span_processor._is_sentry_span(otel_span)

tests/test_dsc.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,19 @@
1313
import pytest
1414

1515
import sentry_sdk
16-
import sentry_sdk.client
16+
from sentry_sdk.transport import Transport
17+
from sentry_sdk.envelope import Envelope
18+
19+
20+
class TransportWithOptions(Transport):
21+
"""Transport does not pass in the options so we need this here"""
22+
23+
def __init__(self, options=None):
24+
Transport.__init__(self, options)
25+
26+
def capture_envelope(self, _: Envelope) -> None:
27+
"""No-op capture_envelope for tests"""
28+
pass
1729

1830

1931
def test_dsc_head_of_trace(sentry_init, capture_envelopes):
@@ -22,10 +34,11 @@ def test_dsc_head_of_trace(sentry_init, capture_envelopes):
2234
and sends a transaction event to Sentry.
2335
"""
2436
sentry_init(
25-
dsn="https://mysecret@bla.ingest.sentry.io/12312012",
37+
dsn="https://mysecret@o1234.ingest.sentry.io/12312012",
2638
release="[email protected]",
2739
environment="canary",
2840
traces_sample_rate=1.0,
41+
transport=TransportWithOptions,
2942
)
3043
envelopes = capture_envelopes()
3144

@@ -45,6 +58,10 @@ def test_dsc_head_of_trace(sentry_init, capture_envelopes):
4558
assert type(envelope_trace_header["public_key"]) == str
4659
assert envelope_trace_header["public_key"] == "mysecret"
4760

61+
assert "org_id" in envelope_trace_header
62+
assert type(envelope_trace_header["org_id"]) == str
63+
assert envelope_trace_header["org_id"] == "1234"
64+
4865
assert "sample_rate" in envelope_trace_header
4966
assert type(envelope_trace_header["sample_rate"]) == str
5067
assert envelope_trace_header["sample_rate"] == "1.0"
@@ -72,10 +89,11 @@ def test_dsc_continuation_of_trace(sentry_init, capture_envelopes):
7289
Our service is continuing the trace and sends a transaction event to Sentry.
7390
"""
7491
sentry_init(
75-
dsn="https://mysecret@bla.ingest.sentry.io/12312012",
92+
dsn="https://mysecret@o1234.ingest.sentry.io/12312012",
7693
release="[email protected]",
7794
environment="canary",
7895
traces_sample_rate=1.0,
96+
transport=TransportWithOptions,
7997
)
8098
envelopes = capture_envelopes()
8199

@@ -149,10 +167,11 @@ def my_traces_sampler(sampling_context):
149167
return 0.25
150168

151169
sentry_init(
152-
dsn="https://mysecret@bla.ingest.sentry.io/12312012",
170+
dsn="https://mysecret@o1234.ingest.sentry.io/12312012",
153171
release="[email protected]",
154172
environment="canary",
155173
traces_sampler=my_traces_sampler,
174+
transport=TransportWithOptions,
156175
)
157176
envelopes = capture_envelopes()
158177

@@ -219,9 +238,10 @@ def test_dsc_issue(sentry_init, capture_envelopes):
219238
Our service is a standalone service that does not have tracing enabled. Just uses Sentry for error reporting.
220239
"""
221240
sentry_init(
222-
dsn="https://mysecret@bla.ingest.sentry.io/12312012",
241+
dsn="https://mysecret@o1234.ingest.sentry.io/12312012",
223242
release="[email protected]",
224243
environment="canary",
244+
transport=TransportWithOptions,
225245
)
226246
envelopes = capture_envelopes()
227247

@@ -244,6 +264,10 @@ def test_dsc_issue(sentry_init, capture_envelopes):
244264
assert type(envelope_trace_header["public_key"]) == str
245265
assert envelope_trace_header["public_key"] == "mysecret"
246266

267+
assert "org_id" in envelope_trace_header
268+
assert type(envelope_trace_header["org_id"]) == str
269+
assert envelope_trace_header["org_id"] == "1234"
270+
247271
assert "sample_rate" not in envelope_trace_header
248272

249273
assert "sampled" not in envelope_trace_header
@@ -265,10 +289,11 @@ def test_dsc_issue_with_tracing(sentry_init, capture_envelopes):
265289
Envelopes containing errors also have the same DSC than the transaction envelopes.
266290
"""
267291
sentry_init(
268-
dsn="https://mysecret@bla.ingest.sentry.io/12312012",
292+
dsn="https://mysecret@o1234.ingest.sentry.io/12312012",
269293
release="[email protected]",
270294
environment="canary",
271295
traces_sample_rate=1.0,
296+
transport=TransportWithOptions,
272297
)
273298
envelopes = capture_envelopes()
274299

@@ -294,6 +319,10 @@ def test_dsc_issue_with_tracing(sentry_init, capture_envelopes):
294319
assert type(envelope_trace_header["public_key"]) == str
295320
assert envelope_trace_header["public_key"] == "mysecret"
296321

322+
assert "org_id" in envelope_trace_header
323+
assert type(envelope_trace_header["org_id"]) == str
324+
assert envelope_trace_header["org_id"] == "1234"
325+
297326
assert "sample_rate" in envelope_trace_header
298327
assert envelope_trace_header["sample_rate"] == "1.0"
299328
assert type(envelope_trace_header["sample_rate"]) == str
@@ -332,10 +361,11 @@ def test_dsc_issue_twp(sentry_init, capture_envelopes, traces_sample_rate):
332361
(This test would be service B in this scenario)
333362
"""
334363
sentry_init(
335-
dsn="https://mysecret@bla.ingest.sentry.io/12312012",
364+
dsn="https://mysecret@o1234.ingest.sentry.io/12312012",
336365
release="[email protected]",
337366
environment="canary",
338367
traces_sample_rate=traces_sample_rate,
368+
transport=TransportWithOptions,
339369
)
340370
envelopes = capture_envelopes()
341371

tests/utils/test_general.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ def test_parse_dsn_paths(given, expected_envelope):
119119
assert auth.get_api_url(EndpointType.ENVELOPE) == expected_envelope
120120

121121

122+
@pytest.mark.parametrize("given,expected", [("https://[email protected]/123", None), ("https://[email protected]/123", "1234")])
123+
def test_parse_dsn_org_id(given, expected):
124+
dsn = Dsn(given)
125+
assert dsn.org_id == expected
126+
127+
122128
@pytest.mark.parametrize(
123129
"dsn",
124130
[

0 commit comments

Comments
 (0)