Skip to content

Commit 3aa65d5

Browse files
authored
feat: Added unified hint api (#61)
1 parent 3140d17 commit 3aa65d5

File tree

8 files changed

+56
-34
lines changed

8 files changed

+56
-34
lines changed

sentry_sdk/api.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33

44
from sentry_sdk.hub import Hub
55
from sentry_sdk.scope import Scope
6-
from sentry_sdk.utils import EventHint
76
from sentry_sdk.transport import Transport, HttpTransport
87
from sentry_sdk.client import Client, get_options
98
from sentry_sdk.integrations import setup_integrations
109

1110

12-
__all__ = ["Hub", "Scope", "Client", "EventHint", "Transport", "HttpTransport"]
11+
__all__ = ["Hub", "Scope", "Client", "Transport", "HttpTransport"]
1312

1413

1514
def public(f):

sentry_sdk/client.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def _prepare_event(self, event, hint, scope):
104104
return event
105105

106106
def _is_ignored_error(self, event, hint=None):
107-
exc_info = hint and hint.exc_info or None
107+
exc_info = hint.get("exc_info")
108108
if exc_info is None:
109109
return False
110110

@@ -123,7 +123,7 @@ def _is_ignored_error(self, event, hint=None):
123123

124124
return False
125125

126-
def _should_capture(self, event, hint=None, scope=None):
126+
def _should_capture(self, event, hint, scope=None):
127127
if (
128128
self.options["sample_rate"] < 1.0
129129
and random.random() >= self.options["sample_rate"]
@@ -140,13 +140,16 @@ def capture_event(self, event, hint=None, scope=None):
140140
141141
This takes the ready made event and an optoinal hint and scope. The
142142
hint is internally used to further customize the representation of the
143-
error. For more information see `EventHint`.
143+
error. When provided it's a dictionary of optional information such
144+
as exception info.
144145
145146
If the transport is not set nothing happens, otherwise the return
146147
value of this function will be the ID of the captured event.
147148
"""
148149
if self.transport is None:
149150
return
151+
if hint is None:
152+
hint = {}
150153
rv = event.get("event_id")
151154
if rv is None:
152155
event["event_id"] = rv = uuid.uuid4().hex

sentry_sdk/hub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def capture_event(self, event, hint=None):
122122
"""Captures an event. The return value is the ID of the event.
123123
124124
The event is a dictionary following the Sentry v7/v8 protocol
125-
specification. Optionally an `EventHint` object can be passed that
125+
specification. Optionally an event hint dict can be passed that
126126
is used by processors to extract additional information from it.
127127
Typically the event hint object would contain exception information.
128128
"""

sentry_sdk/integrations/stdlib.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ def getresponse(self, *args, **kwargs):
4040
if "status_code" not in data:
4141
data["status_code"] = rv.status
4242
data["reason"] = rv.reason
43-
add_breadcrumb(type="http", category="httplib", data=data)
43+
add_breadcrumb(
44+
type="http",
45+
category="httplib",
46+
data=data,
47+
hint={"httplib_response": rv},
48+
)
4449
return rv
4550

4651
self.httplib_connection_cls.putrequest = putrequest

sentry_sdk/scope.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ def _drop(event, cause, ty):
131131
if self._contexts:
132132
event.setdefault("contexts", {}).update(self._contexts)
133133

134-
if hint is not None and hint.exc_info is not None:
135-
exc_info = hint.exc_info
134+
exc_info = hint.get("exc_info") if hint is not None else None
135+
if exc_info is not None:
136136
for processor in self._error_processors:
137137
new_event = processor(event, exc_info)
138138
if new_event is None:

sentry_sdk/utils.py

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,15 @@ def to_timestamp(value):
3636
return (value - epoch).total_seconds()
3737

3838

39-
class EventHint(object):
40-
"""Extra information for an event that can be used during processing."""
41-
42-
def __init__(self, exc_info=None):
43-
self.exc_info = exc_info
44-
45-
@property
46-
def exception(self):
47-
"""Returns the exception value on the hint if there is one."""
48-
if self.exc_info is not None:
49-
return self.exc_info[1]
50-
51-
@classmethod
52-
def with_exc_info(cls, exc_info=None):
53-
"""Creates a hint with the exc info filled in."""
54-
if exc_info is None:
55-
exc_info = sys.exc_info()
56-
else:
57-
exc_info = exc_info_from_error(exc_info)
58-
if exc_info[0] is None:
59-
exc_info = None
60-
return cls(exc_info=exc_info)
39+
def event_hint_with_exc_info(exc_info=None):
40+
"""Creates a hint with the exc info filled in."""
41+
if exc_info is None:
42+
exc_info = sys.exc_info()
43+
else:
44+
exc_info = exc_info_from_error(exc_info)
45+
if exc_info[0] is None:
46+
exc_info = None
47+
return {"exc_info": exc_info}
6148

6249

6350
class BadDsn(ValueError):
@@ -429,7 +416,7 @@ def exc_info_from_error(error):
429416

430417
def event_from_exception(exc_info, with_locals=False, processors=None):
431418
exc_info = exc_info_from_error(exc_info)
432-
hint = EventHint.with_exc_info(exc_info)
419+
hint = event_hint_with_exc_info(exc_info)
433420
return (
434421
{
435422
"level": "error",

tests/integrations/stdlib/test_httplib.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,32 @@ def test_crumb_capture(sentry_init, capture_events):
2626
"status_code": 200,
2727
"reason": "OK",
2828
}
29+
30+
31+
def test_crumb_capture_hint(sentry_init, capture_events):
32+
def before_breadcrumb(crumb, hint):
33+
if "httplib_response" in hint:
34+
con = hint["httplib_response"].getheader("Connection")
35+
assert con.lower() == "close"
36+
crumb["data"]["extra"] = "foo"
37+
return crumb
38+
39+
sentry_init(integrations=[StdlibIntegration()], before_breadcrumb=before_breadcrumb)
40+
events = capture_events()
41+
42+
url = "https://httpbin.org/status/200"
43+
response = urlopen(url)
44+
assert response.getcode() == 200
45+
capture_message("Testing!")
46+
47+
event, = events
48+
crumb, = event["breadcrumbs"]
49+
assert crumb["type"] == "http"
50+
assert crumb["category"] == "httplib"
51+
assert crumb["data"] == {
52+
"url": url,
53+
"method": "GET",
54+
"status_code": 200,
55+
"reason": "OK",
56+
"extra": "foo",
57+
}

tests/test_basics.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ def test_option_callback(sentry_init, capture_events):
5151
drop_breadcrumbs = False
5252

5353
def before_send(event, hint):
54-
assert hint is not None
55-
assert isinstance(hint.exception, ValueError)
54+
assert isinstance(hint["exc_info"][1], ValueError)
5655
if not drop_events:
5756
event["extra"] = {"foo": "bar"}
5857
return event

0 commit comments

Comments
 (0)