Skip to content
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

ref(am): Introduce start_transaction #715

Closed
wants to merge 16 commits into from
Closed

Conversation

untitaker
Copy link
Member

Refactor the API to be similar to getsentry/sentry-javascript#2600

Copy link
Contributor

@rhcarvalho rhcarvalho left a comment

Choose a reason for hiding this comment

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

Thanks for doing it @untitaker. I have a few notes if they can be of any use for improvement. Generally this is looking good.

@@ -462,17 +461,56 @@ def start_span(
else:
span = Span(**kwargs)

if span.sampled is None and span.transaction is not None:
elif isinstance(span, Transaction):
raise ValueError("Pass transactions to start_transaction instead")
Copy link
Contributor

Choose a reason for hiding this comment

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

In JS there is a fallback that calls startTransaction in this case, to ease transition of existing code.

https://github.com/getsentry/sentry-javascript/blob/d66e2d7f76492b2e403f64b047ffaf7bdddabb0a/packages/apm/src/hubextensions.ts#L52-L71

tests/test_tracing.py Outdated Show resolved Hide resolved
tests/test_tracing.py Outdated Show resolved Hide resolved
Comment on lines +169 to +170
with pytest.raises(TypeError):
start_span(name="foo")
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean a runtime error for user code? Should we be more lenient?

Copy link
Member Author

Choose a reason for hiding this comment

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

You always get runtime errors when calling a function with the wrong args. If we want to do a transition path here I think we need to accept transaction as kwarg. Is that what we want?

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO yes, I'd avoid breaking beta users during the upgrade.
Include a clear note of the API change in the change log / release notes, but support the old code path with a warning (message when debug=True) for at least one more release.

tests/test_tracing.py Outdated Show resolved Hide resolved
sentry_sdk/integrations/rq.py Outdated Show resolved Hide resolved
sentry_sdk/integrations/wsgi.py Outdated Show resolved Hide resolved
Comment on lines +144 to +145
if span and isinstance(span, Transaction) and value:
span.name = value
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to store the whole transaction in self._transaction?

Code reading it that expects a string (e.g. to set Event.transaction would read from scope._transaction.name, and code that needs the transaction would read from scope._transaction, removing the need for a scope._span that contains an instance of Transaction.

Copy link
Contributor

Choose a reason for hiding this comment

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

The current state at JS is that we have a single slot for a "span" that can be a transaction or a span. Let's leave this for later.

# type: (**Any) -> Span
"""
Start a sub-span from the current span or transaction.
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels wrong, parent classes (Span) normally do not refer to their subclasses (Transaction).

This would be easy to fix by omitting the "from the current ...", as the context makes it rather clear who is the parent of the new span that is being started.

Suggested change
Start a sub-span from the current span or transaction.
Start a child span.

sentry_sdk/hub.py Show resolved Hide resolved
Co-authored-by: Rodolfo Carvalho <rodolfo.carvalho@sentry.io>
Comment on lines +417 to +422
# At this point a `sampled = None` should have already been
# resolved to a concrete decision. If `sampled` is `None`, it's
# likely that somebody used `with sentry_sdk.Hub.start_span(..)` on a
# non-transaction span and later decided to make it a transaction.
if self.sampled is None:
logger.warning("Discarding transaction Span without sampling decision")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# At this point a `sampled = None` should have already been
# resolved to a concrete decision. If `sampled` is `None`, it's
# likely that somebody used `with sentry_sdk.Hub.start_span(..)` on a
# non-transaction span and later decided to make it a transaction.
if self.sampled is None:
logger.warning("Discarding transaction Span without sampling decision")
# At this point a `sampled = None` should have already been
# resolved to a concrete decision. If `sampled` is `None`, it's
# likely that somebody created a transaction without setting the sampling decision.
# When using `sentry_sdk.Hub.start_transaction(..)` the sampling decision will always be set.
if self.sampled is None:
logger.warning("Discarding transaction without sampling decision")

@@ -194,25 +189,45 @@ def __exit__(self, ty, value, tb):
self.finish(hub)
scope.span = old_span

def new_span(self, **kwargs):
def start_child(self, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this a breaking change for manual instrumentation?
In JS we made sure it's not breaking even if old API is used.

Hub.current is never None. Fixing other occurrences is left for a
separate commit.
sentry_sdk/api.py Outdated Show resolved Hide resolved
Not possible to start a transaction from a span, let's not confuse the
API more.
In favor of replicating start_span's signature.
Example usages:

    Hub.start_transaction(transaction)

or

    Hub.start_transaction(name="...", ...)
It is okay to start a transaction without a name and set it later.
Sometimes the proper name is not known until after the transaction has
started.

We could fail the transaction if it has no name when calling the finish
method. Instead, set a default name that will prompt users to give a
name to their transactions.

This is the same behavior as implemented in JS.
Asserting that each start_transaction context contributes with one and
only one new event makes the overall test more robust -- though far from
perfect, e.g. we make no assertions about the event itself.
@rhcarvalho
Copy link
Contributor

Closing in favor of #747.

@rhcarvalho rhcarvalho closed this Jun 26, 2020
@rhcarvalho rhcarvalho deleted the ref/start-transaction branch June 29, 2020 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants