Skip to content

Commit e873bdb

Browse files
authored
ref(tracing): Pre-traces_sampler documentation additions (getsentry#865)
Comments and docstrings, expanded __repr__s for Span and Transaction, a few variable name changes. No behavior change.
1 parent 097e36d commit e873bdb

File tree

8 files changed

+83
-26
lines changed

8 files changed

+83
-26
lines changed

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
DJANGO_SETTINGS_MODULE = tests.integrations.django.myapp.settings
33
addopts = --tb=short
44
markers =
5-
tests_internal_exceptions
5+
tests_internal_exceptions: Handle internal exceptions just as the SDK does, to test it. (Otherwise internal exceptions are recorded and reraised.)
66
only: A temporary marker, to make pytest only run the tests with the mark, similar to jest's `it.only`. To use, run `pytest -v -m only`.

sentry_sdk/integrations/flask.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ def _request_started(sender, **kwargs):
104104
with hub.configure_scope() as scope:
105105
request = _request_ctx_stack.top.request
106106

107-
# Rely on WSGI middleware to start a trace
107+
# Set the transaction name here, but rely on WSGI middleware to actually
108+
# start the transaction
108109
try:
109110
if integration.transaction_style == "endpoint":
110111
scope.transaction = request.url_rule.endpoint

sentry_sdk/scope.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class Scope(object):
7777
"_level",
7878
"_name",
7979
"_fingerprint",
80+
# note that for legacy reasons, _transaction is the transaction *name*,
81+
# not a Transaction object (the object is stored in _span)
8082
"_transaction",
8183
"_user",
8284
"_tags",

sentry_sdk/tracing.py

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ class Span(object):
111111

112112
def __new__(cls, **kwargs):
113113
# type: (**Any) -> Any
114+
"""
115+
Backwards-compatible implementation of Span and Transaction
116+
creation.
117+
"""
118+
114119
# TODO: consider removing this in a future release.
115120
# This is for backwards compatibility with releases before Transaction
116121
# existed, to allow for a smoother transition.
@@ -166,8 +171,10 @@ def init_span_recorder(self, maxlen):
166171

167172
def __repr__(self):
168173
# type: () -> str
169-
return "<%s(trace_id=%r, span_id=%r, parent_span_id=%r, sampled=%r)>" % (
174+
return "<%s(op=%r, description:%r, trace_id=%r, span_id=%r, parent_span_id=%r, sampled=%r)>" % (
170175
self.__class__.__name__,
176+
self.op,
177+
self.description,
171178
self.trace_id,
172179
self.span_id,
173180
self.parent_span_id,
@@ -200,8 +207,9 @@ def start_child(self, **kwargs):
200207
"""
201208
Start a sub-span from the current span or transaction.
202209
203-
Takes the same arguments as the initializer of :py:class:`Span`. No
204-
attributes other than the sample rate are inherited.
210+
Takes the same arguments as the initializer of :py:class:`Span`. The
211+
trace id, sampling decision, and span recorder are inherited from the
212+
current span/transaction.
205213
"""
206214
kwargs.setdefault("sampled", self.sampled)
207215

@@ -227,6 +235,14 @@ def continue_from_environ(
227235
**kwargs # type: Any
228236
):
229237
# type: (...) -> Transaction
238+
"""
239+
Create a Transaction with the given params, then add in data pulled from
240+
the 'sentry-trace' header in the environ (if any) before returning the
241+
Transaction.
242+
243+
If the 'sentry-trace' header is malformed or missing, just create and
244+
return a Transaction instance with the given params.
245+
"""
230246
if cls is Span:
231247
logger.warning(
232248
"Deprecated: use Transaction.continue_from_environ "
@@ -241,16 +257,25 @@ def continue_from_headers(
241257
**kwargs # type: Any
242258
):
243259
# type: (...) -> Transaction
260+
"""
261+
Create a Transaction with the given params, then add in data pulled from
262+
the 'sentry-trace' header (if any) before returning the Transaction.
263+
264+
If the 'sentry-trace' header is malformed or missing, just create and
265+
return a Transaction instance with the given params.
266+
"""
244267
if cls is Span:
245268
logger.warning(
246269
"Deprecated: use Transaction.continue_from_headers "
247270
"instead of Span.continue_from_headers."
248271
)
249-
parent = Transaction.from_traceparent(headers.get("sentry-trace"), **kwargs)
250-
if parent is None:
251-
parent = Transaction(**kwargs)
252-
parent.same_process_as_parent = False
253-
return parent
272+
transaction = Transaction.from_traceparent(
273+
headers.get("sentry-trace"), **kwargs
274+
)
275+
if transaction is None:
276+
transaction = Transaction(**kwargs)
277+
transaction.same_process_as_parent = False
278+
return transaction
254279

255280
def iter_headers(self):
256281
# type: () -> Generator[Tuple[str, str], None, None]
@@ -263,6 +288,13 @@ def from_traceparent(
263288
**kwargs # type: Any
264289
):
265290
# type: (...) -> Optional[Transaction]
291+
"""
292+
Create a Transaction with the given params, then add in data pulled from
293+
the given 'sentry-trace' header value before returning the Transaction.
294+
295+
If the header value is malformed or missing, just create and return a
296+
Transaction instance with the given params.
297+
"""
266298
if cls is Span:
267299
logger.warning(
268300
"Deprecated: use Transaction.from_traceparent "
@@ -279,20 +311,23 @@ def from_traceparent(
279311
if match is None:
280312
return None
281313

282-
trace_id, span_id, sampled_str = match.groups()
314+
trace_id, parent_span_id, sampled_str = match.groups()
283315

284316
if trace_id is not None:
285317
trace_id = "{:032x}".format(int(trace_id, 16))
286-
if span_id is not None:
287-
span_id = "{:016x}".format(int(span_id, 16))
318+
if parent_span_id is not None:
319+
parent_span_id = "{:016x}".format(int(parent_span_id, 16))
288320

289321
if sampled_str:
290-
sampled = sampled_str != "0" # type: Optional[bool]
322+
parent_sampled = sampled_str != "0" # type: Optional[bool]
291323
else:
292-
sampled = None
324+
parent_sampled = None
293325

294326
return Transaction(
295-
trace_id=trace_id, parent_span_id=span_id, sampled=sampled, **kwargs
327+
trace_id=trace_id,
328+
parent_span_id=parent_span_id,
329+
sampled=parent_sampled,
330+
**kwargs
296331
)
297332

298333
def to_traceparent(self):
@@ -436,16 +471,14 @@ def __init__(
436471

437472
def __repr__(self):
438473
# type: () -> str
439-
return (
440-
"<%s(name=%r, trace_id=%r, span_id=%r, parent_span_id=%r, sampled=%r)>"
441-
% (
442-
self.__class__.__name__,
443-
self.name,
444-
self.trace_id,
445-
self.span_id,
446-
self.parent_span_id,
447-
self.sampled,
448-
)
474+
return "<%s(name=%r, op=%r, trace_id=%r, span_id=%r, parent_span_id=%r, sampled=%r)>" % (
475+
self.__class__.__name__,
476+
self.name,
477+
self.op,
478+
self.trace_id,
479+
self.span_id,
480+
self.parent_span_id,
481+
self.sampled,
449482
)
450483

451484
def finish(self, hub=None):
@@ -454,7 +487,9 @@ def finish(self, hub=None):
454487
# This transaction is already finished, ignore.
455488
return None
456489

490+
# This is a de facto proxy for checking if sampled = False
457491
if self._span_recorder is None:
492+
logger.debug("Discarding transaction because sampled = False")
458493
return None
459494

460495
hub = hub or self.hub or sentry_sdk.Hub.current

tests/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ def _capture_internal_exception(self, exc_info):
4848

4949
@request.addfinalizer
5050
def _():
51+
# rerasise the errors so that this just acts as a pass-through (that
52+
# happens to keep track of the errors which pass through it)
5153
for e in errors:
5254
reraise(*e)
5355

tests/integrations/stdlib/test_httplib.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
import pytest
55

66
try:
7+
# py3
78
from urllib.request import urlopen
89
except ImportError:
10+
# py2
911
from urllib import urlopen
1012

1113
try:
14+
# py2
1215
from httplib import HTTPSConnection
1316
except ImportError:
17+
# py3
1418
from http.client import HTTPSConnection
1519

1620
from sentry_sdk import capture_message

tests/tracing/test_integration_tests.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@ def test_continue_from_headers(sentry_init, capture_events, sampled):
5151
sentry_init(traces_sample_rate=1.0)
5252
events = capture_events()
5353

54+
# make a parent transaction (normally this would be in a different service)
5455
with start_transaction(name="hi"):
5556
with start_span() as old_span:
5657
old_span.sampled = sampled
5758
headers = dict(Hub.current.iter_trace_propagation_headers())
5859

60+
# test that the sampling decision is getting encoded in the header correctly
5961
header = headers["sentry-trace"]
6062
if sampled is True:
6163
assert header.endswith("-1")
@@ -64,6 +66,8 @@ def test_continue_from_headers(sentry_init, capture_events, sampled):
6466
if sampled is None:
6567
assert header.endswith("-")
6668

69+
# child transaction, to prove that we can read 'sentry-trace' header data
70+
# correctly
6771
transaction = Transaction.continue_from_headers(headers, name="WRONG")
6872
assert transaction is not None
6973
assert transaction.sampled == sampled
@@ -72,6 +76,9 @@ def test_continue_from_headers(sentry_init, capture_events, sampled):
7276
assert transaction.parent_span_id == old_span.span_id
7377
assert transaction.span_id != old_span.span_id
7478

79+
# add child transaction to the scope, to show that the captured message will
80+
# be tagged with the trace id (since it happens while the transaction is
81+
# open)
7582
with start_transaction(transaction):
7683
with configure_scope() as scope:
7784
scope.transaction = "ho"

tests/tracing/test_misc.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ def test_span_trimming(sentry_init, capture_events):
1414
pass
1515

1616
(event,) = events
17+
18+
# the transaction is its own first span (which counts for max_spans) but it
19+
# doesn't show up in the span list in the event, so this is 1 less than our
20+
# max_spans value
21+
assert len(event["spans"]) == 2
22+
1723
span1, span2 = event["spans"]
1824
assert span1["op"] == "foo0"
1925
assert span2["op"] == "foo1"

0 commit comments

Comments
 (0)