Skip to content
Open
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
11 changes: 11 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
- The UnraisableHookIntegration is now enabled by default.
- We now don't suppress chained exceptions in the ASGI and asyncio integrations by default. The related `suppress_asgi_chained_exceptions` experimental option was removed.
- In the AWS Lambda and GCP integrations, the message of the warning the SDK optionally emits if a function is about to time out has changed.
- `sentry_sdk.init()` can no longer be used as a context manager.

## Removed

Expand Down Expand Up @@ -82,9 +83,19 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
- The deprecated `propagate_traces` option has been removed. Use `trace_propagation_targets` instead, which gives you more power over trace propagation. Note that only the top-level `init` option was removed; the `propagate_traces` option of the Celery integration remains available.
- Removed Spotlight integration for Django. See [Spotlight 2.0](https://github.com/getsentry/spotlight/issues/891) for more context.
- The deprecated parameter `propagate_hub` in `ThreadingIntegration()` was removed.
- `configure_debug_hub` was removed.
- The `max_spans` option of the `LangchainIntegration` was removed.
- `Baggage.from_options` was removed.
- `Transport.capture_event` was removed. Use `Transport.capture_envelope` instead.
- Function transports were removed.
- The `Scope.trace_propagation_meta` function no longer accepts a `span` as argument.
- Direct assignment to `Scope.level` was removed. Use `Scope.set_level` instead.
- Direct assignment to `Scope.user` was removed. Use `Scope.set_user` instead.
- `Scope.iter_headers` was removed.
- The SDK won't set any tags on its own anymore.
- The `update_current_span` API was removed.


## Deprecated


Expand Down
44 changes: 4 additions & 40 deletions sentry_sdk/_init_implementation.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,15 @@
import re
import warnings
from typing import TYPE_CHECKING

import sentry_sdk
from sentry_sdk.utils import logger, parse_version

if TYPE_CHECKING:
from typing import Any, ContextManager, Optional
from typing import Any, Optional

import sentry_sdk.consts


class _InitGuard:
_CONTEXT_MANAGER_DEPRECATION_WARNING_MESSAGE = (
"Using the return value of sentry_sdk.init as a context manager "
"and manually calling the __enter__ and __exit__ methods on the "
"return value are deprecated. We are no longer maintaining this "
"functionality, and we will remove it in the next major release."
)

def __init__(self, client: "sentry_sdk.Client") -> None:
self._client = client

def __enter__(self) -> "_InitGuard":
warnings.warn(
self._CONTEXT_MANAGER_DEPRECATION_WARNING_MESSAGE,
stacklevel=2,
category=DeprecationWarning,
)

return self

def __exit__(self, exc_type: "Any", exc_value: "Any", tb: "Any") -> None:
warnings.warn(
self._CONTEXT_MANAGER_DEPRECATION_WARNING_MESSAGE,
stacklevel=2,
category=DeprecationWarning,
)

c = self._client
if c is not None:
c.close()


def _check_version_deprecations() -> None:
try:
import gevent
Expand Down Expand Up @@ -71,26 +38,23 @@ def _check_version_deprecations() -> None:
pass


def _init(*args: "Optional[str]", **kwargs: "Any") -> "ContextManager[Any]":
def _init(*args: "Optional[str]", **kwargs: "Any") -> None:
"""Initializes the SDK and optionally integrations.

This takes the same arguments as the client constructor.
"""
client = sentry_sdk.Client(*args, **kwargs)
sentry_sdk.get_global_scope().set_client(client)
_check_version_deprecations()
rv = _InitGuard(client)
return rv


if TYPE_CHECKING:
# Make mypy, PyCharm and other static analyzers think `init` is a type to
# have nicer autocompletion for params.
#
# Use `ClientConstructor` to define the argument types of `init` and
# `ContextManager[Any]` to tell static analyzers about the return type.
# Use `ClientConstructor` to define the argument types of `init`.

class init(sentry_sdk.consts.ClientConstructor, _InitGuard): # noqa: N801
class init(sentry_sdk.consts.ClientConstructor): # noqa: N801
pass

else:
Expand Down
9 changes: 0 additions & 9 deletions sentry_sdk/debug.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import logging
import sys
import warnings
from logging import LogRecord

from sentry_sdk import get_client
Expand All @@ -27,11 +26,3 @@ def configure_logger() -> None:
logger.addHandler(_handler)
logger.setLevel(logging.DEBUG)
logger.addFilter(_DebugFilter())


def configure_debug_hub() -> None:
warnings.warn(
"configure_debug_hub is deprecated. Please remove calls to it, as it is a no-op.",
DeprecationWarning,
stacklevel=2,
)
24 changes: 1 addition & 23 deletions sentry_sdk/integrations/langchain.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import itertools
import json
import sys
import warnings
from collections import OrderedDict
from functools import wraps
from typing import TYPE_CHECKING, NamedTuple
Expand Down Expand Up @@ -236,18 +235,8 @@ class LangchainIntegration(Integration):
def __init__(
self: "LangchainIntegration",
include_prompts: bool = True,
max_spans: "Optional[int]" = None,
) -> None:
self.include_prompts = include_prompts
self.max_spans = max_spans

if max_spans is not None:
warnings.warn(
"The `max_spans` parameter of `LangchainIntegration` is "
"deprecated and will be removed in version 3.0 of sentry-sdk.",
DeprecationWarning,
stacklevel=2,
)

@staticmethod
def setup_once() -> None:
Expand All @@ -274,19 +263,10 @@ def setup_once() -> None:
class SentryLangchainCallback(BaseCallbackHandler):
"""Callback handler that creates Sentry spans."""

def __init__(
self, max_span_map_size: "Optional[int]", include_prompts: bool
) -> None:
def __init__(self, include_prompts: bool) -> None:
self.span_map: "OrderedDict[UUID, Union[sentry_sdk.tracing.Span, StreamedSpan]]" = OrderedDict()
self.max_span_map_size = max_span_map_size
self.include_prompts = include_prompts

def gc_span_map(self) -> None:
if self.max_span_map_size is not None:
while len(self.span_map) > self.max_span_map_size:
run_id, span = self.span_map.popitem(last=False)
self._exit_span(span, run_id)

def _handle_error(self, run_id: "UUID", error: "Any") -> None:
is_ignored = isinstance(error, tuple(LangchainIntegration._ignored_exceptions))

Expand Down Expand Up @@ -356,7 +336,6 @@ def _create_span(

span.__enter__()
self.span_map[run_id] = span
self.gc_span_map()
return span

def _exit_span(
Expand Down Expand Up @@ -1135,7 +1114,6 @@ def new_configure(
for cb in itertools.chain(callbacks_list, inheritable_callbacks_list)
):
sentry_handler = SentryLangchainCallback(
integration.max_spans,
integration.include_prompts,
)
if isinstance(local_callbacks, BaseCallbackManager):
Expand Down
53 changes: 0 additions & 53 deletions sentry_sdk/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
Deque,
Dict,
Generator,
Iterator,
List,
Optional,
ParamSpec,
Expand Down Expand Up @@ -572,18 +571,6 @@ def generate_propagation_context(
if self._propagation_context is None:
self.set_new_propagation_context()

def get_dynamic_sampling_context(self) -> "Optional[Dict[str, str]]":
"""
Returns the Dynamic Sampling Context from the Propagation Context.
If not existing, creates a new one.

Deprecated: Logic moved to PropagationContext, don't use directly.
"""
if self._propagation_context is None:
return None

return self._propagation_context.dynamic_sampling_context

def get_traceparent(self, *args: "Any", **kwargs: "Any") -> "Optional[str]":
"""
Returns the Sentry "sentry-trace" header (aka the traceparent) from the
Expand Down Expand Up @@ -655,27 +642,13 @@ def trace_propagation_meta(self, *args: "Any", **kwargs: "Any") -> str:
Return meta tags which should be injected into HTML templates
to allow propagation of trace information.
"""
span = kwargs.pop("span", None)
if span is not None:
logger.warning(
"The parameter `span` in trace_propagation_meta() is deprecated and will be removed in the future."
)

meta = ""

for name, content in self.iter_trace_propagation_headers():
meta += f'<meta name="{name}" content="{content}">'

return meta

def iter_headers(self) -> "Iterator[Tuple[str, str]]":
"""
Creates a generator which returns the `sentry-trace` and `baggage` headers from the Propagation Context.
Deprecated: use PropagationContext.iter_headers instead.
"""
if self._propagation_context is not None:
yield from self._propagation_context.iter_headers()

def iter_trace_propagation_headers(
self, *args: "Any", **kwargs: "Any"
) -> "Generator[Tuple[str, str], None, None]":
Expand Down Expand Up @@ -759,22 +732,6 @@ def clear(self) -> None:

self._gen_ai_conversation_id: "Optional[str]" = None

@_attr_setter
def level(self, value: "LogLevelStr") -> None:
"""
When set this overrides the level.

.. deprecated:: 1.0.0
Use :func:`set_level` instead.

:param value: The level to set.
"""
logger.warning(
"Deprecated: use .set_level() instead. This will be removed in the future."
)

self._level = value

def set_level(self, value: "LogLevelStr") -> None:
"""
Sets the level for the scope.
Expand Down Expand Up @@ -865,16 +822,6 @@ def set_transaction_name(self, name: str, source: "Optional[str]" = None) -> Non
if source:
self._transaction_info["source"] = source

@_attr_setter
def user(self, value: "Optional[Dict[str, Any]]") -> None:
"""When set a specific user is bound to the scope. Deprecated in favor of set_user."""
warnings.warn(
"The `Scope.user` setter is deprecated in favor of `Scope.set_user()`.",
DeprecationWarning,
stacklevel=2,
)
self.set_user(value)

def set_user(self, value: "Optional[Dict[str, Any]]") -> None:
"""Sets a user for the scope."""
self._user = value
Expand Down
10 changes: 0 additions & 10 deletions sentry_sdk/tracing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,16 +749,6 @@ def from_incoming_header(

return Baggage(sentry_items, third_party_items, mutable)

@classmethod
def from_options(cls, scope: "sentry_sdk.scope.Scope") -> "Optional[Baggage]":
"""
Deprecated: use populate_from_propagation_context
"""
if scope._propagation_context is None:
return Baggage({})

return Baggage.populate_from_propagation_context(scope._propagation_context)

@classmethod
def populate_from_propagation_context(
cls, propagation_context: "PropagationContext"
Expand Down
58 changes: 1 addition & 57 deletions sentry_sdk/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import socket
import ssl
import time
import warnings
from abc import ABC, abstractmethod
from collections import defaultdict
from datetime import datetime, timedelta, timezone
Expand Down Expand Up @@ -68,7 +67,7 @@

from urllib3.poolmanager import PoolManager, ProxyManager

from sentry_sdk._types import Event, EventDataCategory
from sentry_sdk._types import EventDataCategory

KEEP_ALIVE_SOCKET_OPTIONS = []
for option in [
Expand Down Expand Up @@ -113,24 +112,6 @@ def __init__(self: "Self", options: "Optional[Dict[str, Any]]" = None) -> None:
else:
self.parsed_dsn = None

def capture_event(self: "Self", event: "Event") -> None:
"""
DEPRECATED: Please use capture_envelope instead.

This gets invoked with the event dictionary when an event should
be sent to sentry.
"""

warnings.warn(
"capture_event is deprecated, please use capture_envelope instead!",
DeprecationWarning,
stacklevel=2,
)

envelope = Envelope()
envelope.add_event(event)
self.capture_envelope(envelope)

@abstractmethod
def capture_envelope(self: "Self", envelope: "Envelope") -> None:
"""
Expand Down Expand Up @@ -1136,35 +1117,6 @@ def __getattr__(self, name: str) -> "Any":
return getattr(self._inner, name)


class _FunctionTransport(Transport):
"""
DEPRECATED: Users wishing to provide a custom transport should subclass
the Transport class, rather than providing a function.
"""

def __init__(
self,
func: "Callable[[Event], None]",
) -> None:
Transport.__init__(self)
self._func = func

def capture_event(
self,
event: "Event",
) -> None:
self._func(event)
return None

def capture_envelope(self, envelope: "Envelope") -> None:
# Since function transports expect to be called with an event, we need
# to iterate over the envelope and call the function for each event, via
# the deprecated capture_event method.
event = envelope.get_event()
if event is not None:
self.capture_event(event)


Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Callable transports silently send events

High Severity

After function transports were removed, a callable passed as transport is no longer recognized. make_transport then falls through and constructs the default HttpTransport whenever a DSN is set. Callers that still pass a function (for example a no-op or a list-append in tests) will silently send real events to Sentry instead of failing. The ClientConstructor type still lists Callable[[Event], None] as valid, so type checkers will not catch this.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6f4bd53. Configure here.

def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]":
ref_transport = options["transport"]

Expand Down Expand Up @@ -1208,14 +1160,6 @@ def make_transport(options: "Dict[str, Any]") -> "Optional[Transport]":
transport = ref_transport
elif isinstance(ref_transport, type) and issubclass(ref_transport, Transport):
transport_cls = ref_transport
elif callable(ref_transport):
warnings.warn(
"Function transports are deprecated and will be removed in a future release."
"Please provide a Transport instance or subclass, instead.",
DeprecationWarning,
stacklevel=2,
)
transport = _FunctionTransport(ref_transport)

# if a transport class is given only instantiate it if the dsn is not
# empty or None
Expand Down
Loading
Loading