Skip to content

Commit f4f0ec3

Browse files
authored
Merge branch 'master' into dependabot/github_actions/actions/create-github-app-token-1.11.2
2 parents 0d0391e + 1fd2b86 commit f4f0ec3

File tree

13 files changed

+294
-155
lines changed

13 files changed

+294
-155
lines changed

sentry_sdk/_types.py

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,88 @@
1-
from typing import TYPE_CHECKING
1+
from typing import TYPE_CHECKING, TypeVar, Union
22

33

44
# Re-exported for compat, since code out there in the wild might use this variable.
55
MYPY = TYPE_CHECKING
66

77

8+
SENSITIVE_DATA_SUBSTITUTE = "[Filtered]"
9+
10+
11+
class AnnotatedValue:
12+
"""
13+
Meta information for a data field in the event payload.
14+
This is to tell Relay that we have tampered with the fields value.
15+
See:
16+
https://github.com/getsentry/relay/blob/be12cd49a0f06ea932ed9b9f93a655de5d6ad6d1/relay-general/src/types/meta.rs#L407-L423
17+
"""
18+
19+
__slots__ = ("value", "metadata")
20+
21+
def __init__(self, value, metadata):
22+
# type: (Optional[Any], Dict[str, Any]) -> None
23+
self.value = value
24+
self.metadata = metadata
25+
26+
def __eq__(self, other):
27+
# type: (Any) -> bool
28+
if not isinstance(other, AnnotatedValue):
29+
return False
30+
31+
return self.value == other.value and self.metadata == other.metadata
32+
33+
@classmethod
34+
def removed_because_raw_data(cls):
35+
# type: () -> AnnotatedValue
36+
"""The value was removed because it could not be parsed. This is done for request body values that are not json nor a form."""
37+
return AnnotatedValue(
38+
value="",
39+
metadata={
40+
"rem": [ # Remark
41+
[
42+
"!raw", # Unparsable raw data
43+
"x", # The fields original value was removed
44+
]
45+
]
46+
},
47+
)
48+
49+
@classmethod
50+
def removed_because_over_size_limit(cls):
51+
# type: () -> AnnotatedValue
52+
"""The actual value was removed because the size of the field exceeded the configured maximum size (specified with the max_request_body_size sdk option)"""
53+
return AnnotatedValue(
54+
value="",
55+
metadata={
56+
"rem": [ # Remark
57+
[
58+
"!config", # Because of configured maximum size
59+
"x", # The fields original value was removed
60+
]
61+
]
62+
},
63+
)
64+
65+
@classmethod
66+
def substituted_because_contains_sensitive_data(cls):
67+
# type: () -> AnnotatedValue
68+
"""The actual value was removed because it contained sensitive information."""
69+
return AnnotatedValue(
70+
value=SENSITIVE_DATA_SUBSTITUTE,
71+
metadata={
72+
"rem": [ # Remark
73+
[
74+
"!config", # Because of SDK configuration (in this case the config is the hard coded removal of certain django cookies)
75+
"s", # The fields original value was substituted
76+
]
77+
]
78+
},
79+
)
80+
81+
82+
T = TypeVar("T")
83+
Annotated = Union[AnnotatedValue, T]
84+
85+
886
if TYPE_CHECKING:
987
from collections.abc import Container, MutableMapping, Sequence
1088

@@ -19,7 +97,6 @@
1997
from typing import Optional
2098
from typing import Tuple
2199
from typing import Type
22-
from typing import Union
23100
from typing_extensions import Literal, TypedDict
24101

25102
class SDKInfo(TypedDict):
@@ -101,7 +178,7 @@ class SDKInfo(TypedDict):
101178
"request": dict[str, object],
102179
"sdk": Mapping[str, object],
103180
"server_name": str,
104-
"spans": list[dict[str, object]],
181+
"spans": Annotated[list[dict[str, object]]],
105182
"stacktrace": dict[
106183
str, object
107184
], # We access this key in the code, but I am unsure whether we ever set it
@@ -118,6 +195,7 @@ class SDKInfo(TypedDict):
118195
"transaction_info": Mapping[str, Any], # TODO: We can expand on this type
119196
"type": Literal["check_in", "transaction"],
120197
"user": dict[str, object],
198+
"_dropped_spans": int,
121199
"_metrics_summary": dict[str, object],
122200
},
123201
total=False,

sentry_sdk/client.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
from collections.abc import Mapping
66
from datetime import datetime, timezone
77
from importlib import import_module
8-
from typing import cast, overload
8+
from typing import TYPE_CHECKING, List, Dict, cast, overload
99
import warnings
1010

1111
from sentry_sdk._compat import PY37, check_uwsgi_thread_support
1212
from sentry_sdk.utils import (
13+
AnnotatedValue,
1314
ContextVar,
1415
capture_internal_exceptions,
1516
current_stacktrace,
@@ -45,12 +46,9 @@
4546
from sentry_sdk.monitor import Monitor
4647
from sentry_sdk.spotlight import setup_spotlight
4748

48-
from typing import TYPE_CHECKING
49-
5049
if TYPE_CHECKING:
5150
from typing import Any
5251
from typing import Callable
53-
from typing import Dict
5452
from typing import Optional
5553
from typing import Sequence
5654
from typing import Type
@@ -483,12 +481,14 @@ def _prepare_event(
483481
):
484482
# type: (...) -> Optional[Event]
485483

484+
previous_total_spans = None # type: Optional[int]
485+
486486
if event.get("timestamp") is None:
487487
event["timestamp"] = datetime.now(timezone.utc)
488488

489489
if scope is not None:
490490
is_transaction = event.get("type") == "transaction"
491-
spans_before = len(event.get("spans", []))
491+
spans_before = len(cast(List[Dict[str, object]], event.get("spans", [])))
492492
event_ = scope.apply_to_event(event, hint, self.options)
493493

494494
# one of the event/error processors returned None
@@ -507,13 +507,18 @@ def _prepare_event(
507507
return None
508508

509509
event = event_
510-
511-
spans_delta = spans_before - len(event.get("spans", []))
510+
spans_delta = spans_before - len(
511+
cast(List[Dict[str, object]], event.get("spans", []))
512+
)
512513
if is_transaction and spans_delta > 0 and self.transport is not None:
513514
self.transport.record_lost_event(
514515
"event_processor", data_category="span", quantity=spans_delta
515516
)
516517

518+
dropped_spans = event.pop("_dropped_spans", 0) + spans_delta # type: int
519+
if dropped_spans > 0:
520+
previous_total_spans = spans_before + dropped_spans
521+
517522
if (
518523
self.options["attach_stacktrace"]
519524
and "exception" not in event
@@ -561,6 +566,11 @@ def _prepare_event(
561566
if event_scrubber:
562567
event_scrubber.scrub_event(event)
563568

569+
if previous_total_spans is not None:
570+
event["spans"] = AnnotatedValue(
571+
event.get("spans", []), {"len": previous_total_spans}
572+
)
573+
564574
# Postprocess the event here so that annotated types do
565575
# generally not surface in before_send
566576
if event is not None:
@@ -598,7 +608,7 @@ def _prepare_event(
598608
and event.get("type") == "transaction"
599609
):
600610
new_event = None
601-
spans_before = len(event.get("spans", []))
611+
spans_before = len(cast(List[Dict[str, object]], event.get("spans", [])))
602612
with capture_internal_exceptions():
603613
new_event = before_send_transaction(event, hint or {})
604614
if new_event is None:

sentry_sdk/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ def __init__(
528528
profiles_sample_rate=None, # type: Optional[float]
529529
profiles_sampler=None, # type: Optional[TracesSampler]
530530
profiler_mode=None, # type: Optional[ProfilerMode]
531+
profile_session_sample_rate=None, # type: Optional[float]
531532
auto_enabling_integrations=True, # type: bool
532533
disabled_integrations=None, # type: Optional[Sequence[sentry_sdk.integrations.Integration]]
533534
auto_session_tracking=True, # type: bool

sentry_sdk/integrations/grpc/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def _wrap_channel_async(func: Callable[P, AsyncChannel]) -> Callable[P, AsyncCha
8181
"Wrapper for asynchronous secure and insecure channel."
8282

8383
@wraps(func)
84-
def patched_channel(
84+
def patched_channel( # type: ignore
8585
*args: P.args,
8686
interceptors: Optional[Sequence[grpc.aio.ClientInterceptor]] = None,
8787
**kwargs: P.kwargs,
@@ -100,7 +100,7 @@ def _wrap_sync_server(func: Callable[P, Server]) -> Callable[P, Server]:
100100
"""Wrapper for synchronous server."""
101101

102102
@wraps(func)
103-
def patched_server(
103+
def patched_server( # type: ignore
104104
*args: P.args,
105105
interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None,
106106
**kwargs: P.kwargs,
@@ -121,7 +121,7 @@ def _wrap_async_server(func: Callable[P, AsyncServer]) -> Callable[P, AsyncServe
121121
"""Wrapper for asynchronous server."""
122122

123123
@wraps(func)
124-
def patched_aio_server(
124+
def patched_aio_server( # type: ignore
125125
*args: P.args,
126126
interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None,
127127
**kwargs: P.kwargs,

sentry_sdk/integrations/socket.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,19 @@ def setup_once():
2727

2828

2929
def _get_span_description(host, port):
30-
# type: (Union[bytes, str, None], Union[str, int, None]) -> str
30+
# type: (Union[bytes, str, None], Union[bytes, str, int, None]) -> str
3131

3232
try:
3333
host = host.decode() # type: ignore
3434
except (UnicodeDecodeError, AttributeError):
3535
pass
3636

37-
description = "%s:%s" % (host, port) # type: ignore
37+
try:
38+
port = port.decode() # type: ignore
39+
except (UnicodeDecodeError, AttributeError):
40+
pass
3841

42+
description = "%s:%s" % (host, port) # type: ignore
3943
return description
4044

4145

@@ -74,7 +78,7 @@ def _patch_getaddrinfo():
7478
real_getaddrinfo = socket.getaddrinfo
7579

7680
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
77-
# type: (Union[bytes, str, None], Union[str, int, None], int, int, int, int) -> List[Tuple[AddressFamily, SocketKind, int, str, Union[Tuple[str, int], Tuple[str, int, int, int]]]]
81+
# type: (Union[bytes, str, None], Union[bytes, str, int, None], int, int, int, int) -> List[Tuple[AddressFamily, SocketKind, int, str, Union[Tuple[str, int], Tuple[str, int, int, int], Tuple[int, bytes]]]]
7882
integration = sentry_sdk.get_client().get_integration(SocketIntegration)
7983
if integration is None:
8084
return real_getaddrinfo(host, port, family, type, proto, flags)
@@ -89,4 +93,4 @@ def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
8993

9094
return real_getaddrinfo(host, port, family, type, proto, flags)
9195

92-
socket.getaddrinfo = getaddrinfo # type: ignore
96+
socket.getaddrinfo = getaddrinfo

sentry_sdk/integrations/tornado.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ async def sentry_execute_request_handler(self, *args, **kwargs):
7979
else:
8080

8181
@coroutine # type: ignore
82-
def sentry_execute_request_handler(self, *args, **kwargs):
82+
def sentry_execute_request_handler(self, *args, **kwargs): # type: ignore
8383
# type: (RequestHandler, *Any, **Any) -> Any
8484
with _handle_request_impl(self):
8585
result = yield from old_execute(self, *args, **kwargs)

0 commit comments

Comments
 (0)