Skip to content

Create spans on scope #3442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh

### Changed

- `sentry_sdk.start_span` now only takes keyword arguments.

### Removed

### Deprecated

- `sentry_sdk.start_transaction` is deprecated. Use `sentry_sdk.start_span` instead.

## Upgrading to 2.0

Expand Down
24 changes: 20 additions & 4 deletions sentry_sdk/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import inspect

from sentry_sdk import tracing, tracing_utils, Client
from sentry_sdk import tracing_utils, Client
from sentry_sdk._init_implementation import init
from sentry_sdk.tracing import POTelSpan, Transaction, trace
from sentry_sdk.crons import monitor
Expand Down Expand Up @@ -233,14 +233,26 @@ def flush(


def start_span(
*,
span=None,
custom_sampling_context=None,
**kwargs, # type: Any
):
# type: (...) -> POTelSpan
"""
Alias for tracing.POTelSpan constructor. The method signature is the same.
Start and return a span.

This is the entry point to manual tracing instrumentation.

A tree structure can be built by adding child spans to the span.
To start a new child span within the span, call the `start_child()` method.

When used as a context manager, spans are automatically finished at the end
of the `with` block. If not using context managers, call the `finish()`
method.
"""
# TODO: Consider adding type hints to the method signature.
return tracing.POTelSpan(**kwargs)
return get_current_scope().start_span(span, custom_sampling_context, **kwargs)


def start_transaction(
Expand Down Expand Up @@ -282,7 +294,11 @@ def start_transaction(
constructor. See :py:class:`sentry_sdk.tracing.Transaction` for
available arguments.
"""
return start_span(**kwargs)
return start_span(
span=transaction,
custom_sampling_context=custom_sampling_context,
**kwargs,
)


def set_measurement(name, value, unit=""):
Expand Down
39 changes: 11 additions & 28 deletions sentry_sdk/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
NoOpSpan,
Span,
Transaction,
POTelSpan,
)
from sentry_sdk._types import TYPE_CHECKING
from sentry_sdk.utils import (
Expand Down Expand Up @@ -963,6 +964,10 @@ def start_transaction(
):
# type: (Optional[Transaction], Optional[SamplingContext], Unpack[TransactionKwargs]) -> Union[Transaction, NoOpSpan]
"""
.. deprecated:: 3.0.0
This function is deprecated and will be removed in a future release.
Use :py:meth:`sentry_sdk.start_span` instead.

Start and return a transaction.

Start an existing transaction if given, otherwise create and start a new
Expand Down Expand Up @@ -993,19 +998,12 @@ def start_transaction(
"""
kwargs.setdefault("scope", self)

client = self.get_client()

try_autostart_continuous_profiler()

custom_sampling_context = custom_sampling_context or {}

# kwargs at this point has type TransactionKwargs, since we have removed
# the client and custom_sampling_context from it.
transaction_kwargs = kwargs # type: TransactionKwargs

# if we haven't been given a transaction, make one
if transaction is None:
transaction = Transaction(**transaction_kwargs)
transaction = transaction or POTelSpan(**kwargs)

# use traces_sample_rate, traces_sampler, and/or inheritance to make a
# sampling decision
Expand All @@ -1024,39 +1022,24 @@ def start_transaction(

transaction._profile = profile

# we don't bother to keep spans if we already know we're not going to
# send the transaction
max_spans = (client.options["_experiments"].get("max_spans")) or 1000
transaction.init_span_recorder(maxlen=max_spans)

return transaction

def start_span(self, **kwargs):
# type: (Any) -> Span
def start_span(self, span=None, custom_sampling_context=None, **kwargs):
# type: (Optional[Span], Optional[SamplingContext], Any) -> Span
"""
Start a span whose parent is the currently active span or transaction, if any.
Start a span whose parent is the currently active span, if any.

The return value is a :py:class:`sentry_sdk.tracing.Span` instance,
typically used as a context manager to start and stop timing in a `with`
block.

Only spans contained in a transaction are sent to Sentry. Most
integrations start a transaction at the appropriate time, for example
for every incoming HTTP request. Use
:py:meth:`sentry_sdk.start_transaction` to start a new transaction when
one is not already in progress.

For supported `**kwargs` see :py:class:`sentry_sdk.tracing.Span`.

The instrumenter parameter is deprecated for user code, and it will
be removed in the next major version. Going forward, it should only
be used by the SDK itself.
"""
with new_scope():
kwargs.setdefault("scope", self)

# get current span or transaction
span = self.span or self.get_isolation_scope().span
span = span or self.span or self.get_isolation_scope().span

if span is None:
# New spans get the `trace_id` from the scope
Expand All @@ -1065,7 +1048,7 @@ def start_span(self, **kwargs):
if propagation_context is not None:
kwargs["trace_id"] = propagation_context.trace_id

span = Span(**kwargs)
span = POTelSpan(**kwargs)
else:
# Children take `trace_id`` from the parent span.
span = span.start_child(**kwargs)
Expand Down
17 changes: 13 additions & 4 deletions sentry_sdk/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,10 @@ def containing_transaction(self):

def start_child(self, **kwargs):
# type: (str, **Any) -> POTelSpan
pass
kwargs.setdefault("sampled", self.sampled)

span = POTelSpan(**kwargs)
return span

@classmethod
def continue_from_environ(
Expand All @@ -1317,7 +1320,9 @@ def continue_from_environ(
**kwargs, # type: Any
):
# type: (...) -> POTelSpan
pass
# XXX actually propagate
span = POTelSpan(**kwargs)
return span
Comment on lines +1323 to +1325
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This (and the stuff below) is here so that we get at least some spans from the continue_from_* methods


@classmethod
def continue_from_headers(
Expand All @@ -1326,7 +1331,9 @@ def continue_from_headers(
**kwargs, # type: Any
):
# type: (...) -> POTelSpan
pass
# XXX actually propagate
span = POTelSpan(**kwargs)
return span

def iter_headers(self):
# type: () -> Iterator[Tuple[str, str]]
Expand All @@ -1339,7 +1346,9 @@ def from_traceparent(
**kwargs, # type: Any
):
# type: (...) -> Optional[Transaction]
pass
# XXX actually propagate
span = POTelSpan(**kwargs)
return span

def to_traceparent(self):
# type: () -> str
Expand Down
Loading