diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 6da9870a5f..f4789d5306 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -332,7 +332,7 @@ def capture_event( # this is outside of the `if` immediately below because even if we don't # use the value, we want to make sure we remove it before the event is - # sent (which the `.pop()` does) + # sent raw_tracestate = ( event_opt.get("contexts", {}).get("trace", {}).pop("tracestate", "") ) diff --git a/sentry_sdk/integrations/httpx.py b/sentry_sdk/integrations/httpx.py index af67315338..3d4bbf8300 100644 --- a/sentry_sdk/integrations/httpx.py +++ b/sentry_sdk/integrations/httpx.py @@ -1,5 +1,6 @@ from sentry_sdk import Hub from sentry_sdk.integrations import Integration, DidNotEnable +from sentry_sdk.utils import logger from sentry_sdk._types import MYPY @@ -45,6 +46,11 @@ def send(self, request, **kwargs): span.set_data("method", request.method) span.set_data("url", str(request.url)) for key, value in hub.iter_trace_propagation_headers(): + logger.debug( + "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format( + key=key, value=value, url=request.url + ) + ) request.headers[key] = value rv = real_send(self, request, **kwargs) @@ -72,6 +78,11 @@ async def send(self, request, **kwargs): span.set_data("method", request.method) span.set_data("url", str(request.url)) for key, value in hub.iter_trace_propagation_headers(): + logger.debug( + "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format( + key=key, value=value, url=request.url + ) + ) request.headers[key] = value rv = await real_send(self, request, **kwargs) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 405b95c372..adea742b2d 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -7,7 +7,7 @@ from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor from sentry_sdk.tracing_utils import EnvironHeaders -from sentry_sdk.utils import capture_internal_exceptions, safe_repr +from sentry_sdk.utils import capture_internal_exceptions, logger, safe_repr from sentry_sdk._types import MYPY @@ -86,6 +86,11 @@ def putrequest(self, method, url, *args, **kwargs): rv = real_putrequest(self, method, url, *args, **kwargs) for key, value in hub.iter_trace_propagation_headers(span): + logger.debug( + "[Tracing] Adding `{key}` header {value} to outgoing request to {real_url}.".format( + key=key, value=value, real_url=real_url + ) + ) self.putheader(key, value) self._sentrysdk_span = span diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index ccf6f4e086..f7070e8a02 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -174,7 +174,7 @@ def transaction(self, value): # anything set in the scope. # XXX: note that with the introduction of the Scope.transaction getter, # there is a semantic and type mismatch between getter and setter. The - # getter returns a transaction, the setter sets a transaction name. + # getter returns a Transaction, the setter sets a transaction name. # Without breaking version compatibility, we could make the setter set a # transaction name or transaction (self._span) depending on the type of # the value argument. diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 2fa06a85b4..7235adbb95 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -22,12 +22,12 @@ if MYPY: import typing - from typing import Generator from typing import Optional from typing import Any from typing import Dict from typing import List from typing import Tuple + from typing import Iterator from sentry_sdk._types import SamplingContext @@ -183,19 +183,19 @@ def start_child(self, **kwargs): """ kwargs.setdefault("sampled", self.sampled) - rv = Span( + child = Span( trace_id=self.trace_id, span_id=None, parent_span_id=self.span_id, **kwargs ) if isinstance(self, Transaction): - rv._containing_transaction = self + child._containing_transaction = self else: - rv._containing_transaction = self._containing_transaction + child._containing_transaction = self._containing_transaction - rv._span_recorder = recorder = self._span_recorder + child._span_recorder = recorder = self._span_recorder if recorder: - recorder.add(rv) - return rv + recorder.add(child) + return child def new_span(self, **kwargs): # type: (**Any) -> Span @@ -253,9 +253,15 @@ def continue_from_headers( return transaction def iter_headers(self): - # type: () -> Generator[Tuple[str, str], None, None] + # type: () -> Iterator[Tuple[str, str]] + """ + Creates a generator which returns the span's `sentry-trace` and + `tracestate` headers. + """ yield "sentry-trace", self.to_traceparent() + tracestate = self.to_tracestate() + # `tracestate` will only be `None` if there's no client or no DSN if tracestate: yield "tracestate", tracestate @@ -295,9 +301,11 @@ def to_traceparent(self): def to_tracestate(self): # type: () -> Optional[str] """ - Generates the `tracestate` header value to attach to outgoing requests. + Computes the `tracestate` header value using data from the containing + transaction. + + Returns None if there's no client and/or no DSN. """ - header_value = None if isinstance(self, Transaction): transaction = self # type: Optional[Transaction] diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index f13a81a026..d3c53a971e 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -285,6 +285,9 @@ def compute_tracestate_value(data): # type: (typing.Mapping[str, str]) -> str """ Computes a new tracestate value using the given data. + + Note: Returns just the base64-encoded data, NOT the full `sentry=...` + tracestate entry. """ tracestate_json = json.dumps(data) @@ -300,7 +303,9 @@ def compute_tracestate_value(data): def compute_tracestate_entry(span): # type: (Span) -> str """ - Computes a new tracestate value for the span. + Computes a new sentry tracestate for the span. Includes the `sentry=`. + + Will return `None` if there's no client and/or no DSN. """ data = {}