Skip to content

Commit

Permalink
Merge branch 'master' into m.redis-cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
szokeasaurusrex committed Dec 7, 2023
2 parents d5c5a99 + 0eb3465 commit 3360168
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 111 deletions.
17 changes: 17 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Describe your PR here -->

---

## General Notes

Thank you for contributing to `sentry-python`!

Please add tests to validate your changes, and lint your code using `tox -e linters`.

Running the test suite on your PR might require maintainer approval. Some tests (AWS Lambda) additionally require a maintainer to add a special label to run and will fail if the label is not present.

#### For maintainers

Sensitive test suites require maintainer review to ensure that tests do not compromise our secrets. This review must be repeated after any code revisions.

Before running sensitive test suites, please carefully check the PR. Then, apply the `Trigger: tests using secrets` label. The label will be removed after any code changes to enforce our policy requiring maintainers to review all code revisions before running sensitive tests.
19 changes: 19 additions & 0 deletions sentry_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@
from typing import Dict
from typing import Optional
from typing import Sequence
from typing import Type
from typing import Union

from sentry_sdk.integrations import Integration
from sentry_sdk.scope import Scope
from sentry_sdk._types import Event, Hint
from sentry_sdk.session import Session
Expand Down Expand Up @@ -653,6 +656,22 @@ def capture_session(
else:
self.session_flusher.add_session(session)

def get_integration(
self, name_or_class # type: Union[str, Type[Integration]]
):
# type: (...) -> Any
"""Returns the integration for this client by name or class.
If the client does not have that integration then `None` is returned.
"""
if isinstance(name_or_class, str):
integration_name = name_or_class
elif name_or_class.identifier is not None:
integration_name = name_or_class.identifier
else:
raise ValueError("Integration has no name")

return self.integrations.get(integration_name)

def close(
self,
timeout=None, # type: Optional[float]
Expand Down
62 changes: 10 additions & 52 deletions sentry_sdk/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from contextlib import contextmanager

from sentry_sdk._compat import datetime_utcnow, with_metaclass
from sentry_sdk._compat import with_metaclass
from sentry_sdk.consts import INSTRUMENTER
from sentry_sdk.scope import Scope
from sentry_sdk.client import Client
Expand All @@ -15,7 +15,6 @@
BAGGAGE_HEADER_NAME,
SENTRY_TRACE_HEADER_NAME,
)
from sentry_sdk.session import Session
from sentry_sdk.tracing_utils import (
has_tracing_enabled,
normalize_incoming_data,
Expand Down Expand Up @@ -294,18 +293,9 @@ def get_integration(
If the return value is not `None` the hub is guaranteed to have a
client attached.
"""
if isinstance(name_or_class, str):
integration_name = name_or_class
elif name_or_class.identifier is not None:
integration_name = name_or_class.identifier
else:
raise ValueError("Integration has no name")

client = self.client
if client is not None:
rv = client.integrations.get(integration_name)
if rv is not None:
return rv
return client.get_integration(name_or_class)

@property
def client(self):
Expand Down Expand Up @@ -430,31 +420,9 @@ def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
logger.info("Dropped breadcrumb because no client bound")
return

crumb = dict(crumb or ()) # type: Breadcrumb
crumb.update(kwargs)
if not crumb:
return

hint = dict(hint or ()) # type: Hint

if crumb.get("timestamp") is None:
crumb["timestamp"] = datetime_utcnow()
if crumb.get("type") is None:
crumb["type"] = "default"

if client.options["before_breadcrumb"] is not None:
new_crumb = client.options["before_breadcrumb"](crumb, hint)
else:
new_crumb = crumb

if new_crumb is not None:
scope._breadcrumbs.append(new_crumb)
else:
logger.info("before breadcrumb dropped breadcrumb (%s)", crumb)
kwargs["client"] = client

max_breadcrumbs = client.options["max_breadcrumbs"] # type: int
while len(scope._breadcrumbs) > max_breadcrumbs:
scope._breadcrumbs.popleft()
scope.add_breadcrumb(crumb, hint, **kwargs)

def start_span(self, span=None, instrumenter=INSTRUMENTER.SENTRY, **kwargs):
# type: (Optional[Span], str, Any) -> Span
Expand Down Expand Up @@ -712,26 +680,17 @@ def start_session(
):
# type: (...) -> None
"""Starts a new session."""
self.end_session()
client, scope = self._stack[-1]
scope._session = Session(
release=client.options["release"] if client else None,
environment=client.options["environment"] if client else None,
user=scope._user,
scope.start_session(
client=client,
session_mode=session_mode,
)

def end_session(self):
# type: (...) -> None
"""Ends the current session if there is one."""
client, scope = self._stack[-1]
session = scope._session
self.scope._session = None

if session is not None:
session.close()
if client is not None:
client.capture_session(session)
scope.end_session(client=client)

def stop_auto_session_tracking(self):
# type: (...) -> None
Expand All @@ -740,18 +699,17 @@ def stop_auto_session_tracking(self):
This temporarily session tracking for the current scope when called.
To resume session tracking call `resume_auto_session_tracking`.
"""
self.end_session()
client, scope = self._stack[-1]
scope._force_auto_session_tracking = False
scope.stop_auto_session_tracking(client=client)

def resume_auto_session_tracking(self):
# type: (...) -> None
"""Resumes automatic session tracking for the current scope if
disabled earlier. This requires that generally automatic session
tracking is enabled.
"""
client, scope = self._stack[-1]
scope._force_auto_session_tracking = None
scope = self._stack[-1][1]
scope.resume_auto_session_tracking()

def flush(
self,
Expand Down
18 changes: 10 additions & 8 deletions sentry_sdk/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,20 +375,22 @@ def add(

def to_json(self):
# type: (...) -> Dict[str, Any]
rv = {}
rv = {} # type: Any
for (export_key, tags), (
v_min,
v_max,
v_count,
v_sum,
) in self._measurements.items():
rv[export_key] = {
"tags": _tags_to_dict(tags),
"min": v_min,
"max": v_max,
"count": v_count,
"sum": v_sum,
}
rv.setdefault(export_key, []).append(
{
"tags": _tags_to_dict(tags),
"min": v_min,
"max": v_max,
"count": v_count,
"sum": v_sum,
}
)
return rv


Expand Down
99 changes: 95 additions & 4 deletions sentry_sdk/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import uuid

from sentry_sdk.attachments import Attachment
from sentry_sdk._compat import datetime_utcnow
from sentry_sdk.consts import FALSE_VALUES
from sentry_sdk._functools import wraps
from sentry_sdk.session import Session
from sentry_sdk.tracing_utils import (
Baggage,
extract_sentrytrace_data,
Expand All @@ -20,9 +23,6 @@
from sentry_sdk._types import TYPE_CHECKING
from sentry_sdk.utils import logger, capture_internal_exceptions

from sentry_sdk.consts import FALSE_VALUES


if TYPE_CHECKING:
from typing import Any
from typing import Dict
Expand All @@ -36,6 +36,7 @@

from sentry_sdk._types import (
Breadcrumb,
BreadcrumbHint,
Event,
EventProcessor,
ErrorProcessor,
Expand All @@ -46,7 +47,6 @@

from sentry_sdk.profiler import Profile
from sentry_sdk.tracing import Span
from sentry_sdk.session import Session

F = TypeVar("F", bound=Callable[..., Any])
T = TypeVar("T")
Expand Down Expand Up @@ -517,6 +517,97 @@ def add_attachment(
)
)

def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
# type: (Optional[Breadcrumb], Optional[BreadcrumbHint], Any) -> None
"""
Adds a breadcrumb.
:param crumb: Dictionary with the data as the sentry v7/v8 protocol expects.
:param hint: An optional value that can be used by `before_breadcrumb`
to customize the breadcrumbs that are emitted.
"""
client = kwargs.pop("client", None)
if client is None:
return

before_breadcrumb = client.options.get("before_breadcrumb")
max_breadcrumbs = client.options.get("max_breadcrumbs")

crumb = dict(crumb or ()) # type: Breadcrumb
crumb.update(kwargs)
if not crumb:
return

hint = dict(hint or ()) # type: Hint

if crumb.get("timestamp") is None:
crumb["timestamp"] = datetime_utcnow()
if crumb.get("type") is None:
crumb["type"] = "default"

if before_breadcrumb is not None:
new_crumb = before_breadcrumb(crumb, hint)
else:
new_crumb = crumb

if new_crumb is not None:
self._breadcrumbs.append(new_crumb)
else:
logger.info("before breadcrumb dropped breadcrumb (%s)", crumb)

while len(self._breadcrumbs) > max_breadcrumbs:
self._breadcrumbs.popleft()

def start_session(self, *args, **kwargs):
# type: (*Any, **Any) -> None
"""Starts a new session."""
client = kwargs.pop("client", None)
session_mode = kwargs.pop("session_mode", "application")

self.end_session(client=client)

self._session = Session(
release=client.options["release"] if client else None,
environment=client.options["environment"] if client else None,
user=self._user,
session_mode=session_mode,
)

def end_session(self, *args, **kwargs):
# type: (*Any, **Any) -> None
"""Ends the current session if there is one."""
client = kwargs.pop("client", None)

session = self._session
self._session = None

if session is not None:
session.close()
if client is not None:
client.capture_session(session)

def stop_auto_session_tracking(self, *args, **kwargs):
# type: (*Any, **Any) -> None
"""Stops automatic session tracking.
This temporarily session tracking for the current scope when called.
To resume session tracking call `resume_auto_session_tracking`.
"""
client = kwargs.pop("client", None)

self.end_session(client=client)

self._force_auto_session_tracking = False

def resume_auto_session_tracking(self):
# type: (...) -> None
"""Resumes automatic session tracking for the current scope if
disabled earlier. This requires that generally automatic session
tracking is enabled.
"""
self._force_auto_session_tracking = None

def add_event_processor(
self, func # type: EventProcessor
):
Expand Down
Loading

0 comments on commit 3360168

Please sign in to comment.