-
Notifications
You must be signed in to change notification settings - Fork 555
ref(am): Introduce start_transaction #715
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
Changes from 1 commit
2e37add
2756487
153b5a9
bdfc417
7ce76f0
a488d1e
dc8ffc3
80275ef
63a4681
e8349ea
5036f28
429c842
af2b1e3
986c9f1
a32e2d0
a845863
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
from sentry_sdk._compat import with_metaclass | ||
from sentry_sdk.scope import Scope | ||
from sentry_sdk.client import Client | ||
from sentry_sdk.tracing import Span | ||
from sentry_sdk.tracing import Span, Transaction | ||
from sentry_sdk.sessions import Session | ||
from sentry_sdk.utils import ( | ||
exc_info_from_error, | ||
|
@@ -445,10 +445,9 @@ def start_span( | |
span, if any. The return value is the span object that can | ||
be used as a context manager to start and stop timing. | ||
|
||
Note that you will not see any span that is not contained | ||
within a transaction. Create a transaction with | ||
``start_span(transaction="my transaction")`` if an | ||
integration doesn't already do this for you. | ||
Note that you will not see any span that is not contained within a | ||
transaction. Most integrations already do this for you, but create a | ||
transaction with `start_transaction` otherwise. | ||
""" | ||
|
||
client, scope = self._stack[-1] | ||
|
@@ -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") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In JS there is a fallback that calls |
||
|
||
return span | ||
|
||
def start_transaction( | ||
self, | ||
span_or_name=None, # type: Optional[Union[Span, str]] | ||
rhcarvalho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
**kwargs # type: Any | ||
): | ||
# type: (...) -> Transaction | ||
""" | ||
Create a new transaction detached from the current span. The return | ||
value is the `Transaction` object which for the most part works like a | ||
span. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Here we say "current span", in Do we even need to talk about "detached from"? When I call a function my usual expectation is that it is not causing unexpected side effects. It is useful to document side effects, strange to document the lack of side effects, unless we're making a direct comparison with something else.
I feel this is confusing because it does not explain what the difference is. We were trying to help make this distinction more clear for users. Start transaction returns a transaction. Transactions contain spans. Transactions are sent to Sentry when finished. If we want to go into more details of what a Here it would be more relevant to explain when someone would want to use this function. In JS we describe that this is the entry point for doing manual instrumentation. |
||
""" | ||
|
||
kwargs.setdefault("hub", self) | ||
|
||
if isinstance(span_or_name, str): | ||
if "name" in kwargs: | ||
raise ValueError("Cannot specify transaction name twice.") | ||
kwargs["name"] = span_or_name | ||
transaction = Transaction(**kwargs) | ||
|
||
elif span_or_name is None and "name" in kwargs: | ||
transaction = Transaction(**kwargs) | ||
|
||
elif isinstance(span_or_name, Transaction): | ||
transaction = span_or_name | ||
rhcarvalho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
elif span_or_name is None and "span" in kwargs: | ||
transaction = kwargs.pop("span") | ||
rhcarvalho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
else: | ||
raise ValueError("transaction object or name required.") | ||
|
||
client, scope = self._stack[-1] | ||
|
||
if transaction.sampled is None: | ||
sample_rate = client and client.options["traces_sample_rate"] or 0 | ||
span.sampled = random.random() < sample_rate | ||
transaction.sampled = random.random() < sample_rate | ||
rhcarvalho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if span.sampled: | ||
if transaction.sampled: | ||
max_spans = ( | ||
client and client.options["_experiments"].get("max_spans") or 1000 | ||
) | ||
span.init_finished_spans(maxlen=max_spans) | ||
transaction.init_span_recorder(maxlen=max_spans) | ||
|
||
return span | ||
return transaction | ||
|
||
@overload # noqa | ||
def push_scope( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
|
||
from sentry_sdk.hub import Hub | ||
from sentry_sdk.utils import capture_internal_exceptions, event_from_exception | ||
from sentry_sdk.tracing import Span | ||
from sentry_sdk.tracing import Transaction | ||
from sentry_sdk._compat import reraise | ||
from sentry_sdk.integrations import Integration, DidNotEnable | ||
from sentry_sdk.integrations.logging import ignore_logger | ||
|
@@ -130,19 +130,21 @@ def _inner(*args, **kwargs): | |
scope.clear_breadcrumbs() | ||
scope.add_event_processor(_make_event_processor(task, *args, **kwargs)) | ||
|
||
span = Span.continue_from_headers(args[3].get("headers") or {}) | ||
span.op = "celery.task" | ||
span.transaction = "unknown celery task" | ||
span = Transaction.continue_from_headers( | ||
rhcarvalho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
args[3].get("headers") or {}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see this was already there. What is |
||
op="celery.task", | ||
name="unknown celery task", | ||
) | ||
|
||
# Could possibly use a better hook than this one | ||
span.set_status("ok") | ||
|
||
with capture_internal_exceptions(): | ||
# Celery task objects are not a thing to be trusted. Even | ||
# something such as attribute access can fail. | ||
span.transaction = task.name | ||
span.name = task.name | ||
|
||
with hub.start_span(span): | ||
with hub.start_transaction(span): | ||
return f(*args, **kwargs) | ||
|
||
return _inner # type: ignore | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
from sentry_sdk._functools import wraps | ||
from sentry_sdk._types import MYPY | ||
from sentry_sdk.utils import logger, capture_internal_exceptions | ||
from sentry_sdk.tracing import Transaction | ||
|
||
if MYPY: | ||
from typing import Any | ||
|
@@ -140,8 +141,8 @@ def transaction(self, value): | |
"""When set this forces a specific transaction name to be set.""" | ||
self._transaction = value | ||
span = self._span | ||
if span: | ||
span.transaction = value | ||
if span and isinstance(span, Transaction) and value: | ||
span.name = value | ||
Comment on lines
+144
to
+145
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to store the whole transaction in Code reading it that expects a string (e.g. to set There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
@_attr_setter | ||
def user(self, value): | ||
|
@@ -166,8 +167,8 @@ def span(self): | |
def span(self, span): | ||
# type: (Optional[Span]) -> None | ||
self._span = span | ||
if span is not None: | ||
span_transaction = span.transaction | ||
if isinstance(span, Transaction): | ||
span_transaction = span.name | ||
if span_transaction: | ||
self._transaction = span_transaction | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.