Skip to content

Commit e57f70c

Browse files
authored
Release v4.6.2
2 parents b22ab1f + e945a99 commit e57f70c

File tree

8 files changed

+82
-18
lines changed

8 files changed

+82
-18
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
## v4.6.2 (2024-03-05)
5+
6+
### Bug fixes
7+
8+
* Ensure sessions are sent at exit
9+
[#371](https://github.com/bugsnag/bugsnag-python/pull/371)
10+
411
## v4.6.1 (2023-12-11)
512

613
### Bug fixes

bugsnag/configuration.py

+19
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,25 @@ def delivery(self):
273273
def delivery(self, value):
274274
if hasattr(value, 'deliver') and callable(value.deliver):
275275
self._delivery = value
276+
277+
# deliver_sessions is _technically_ optional in that if you disable
278+
# session tracking it will never be called
279+
# this should be made mandatory in the next major release
280+
if (
281+
hasattr(value, 'deliver_sessions') and
282+
callable(value.deliver_sessions)
283+
):
284+
parameter_names = value.deliver_sessions.__code__.co_varnames
285+
286+
if 'options' not in parameter_names:
287+
warnings.warn(
288+
'delivery.deliver_sessions should accept an ' +
289+
'"options" parameter to allow for synchronous ' +
290+
'delivery, sessions may be lost when the process ' +
291+
'exits',
292+
DeprecationWarning
293+
)
294+
276295
else:
277296
message = ('delivery should implement Delivery interface, got ' +
278297
'{0}. This will be an error in a future release.')

bugsnag/delivery.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ class Delivery:
5555
def __init__(self):
5656
self.sent_session_warning = False
5757

58-
def deliver(self, config, payload: Any, options={}):
58+
def deliver(self, config, payload: Any, options=None):
5959
"""
6060
Sends error reports to Bugsnag
6161
"""
6262
pass
6363

64-
def deliver_sessions(self, config, payload: Any):
64+
def deliver_sessions(self, config, payload: Any, options=None):
6565
"""
6666
Sends sessions to Bugsnag
6767
"""
@@ -72,10 +72,12 @@ def deliver_sessions(self, config, payload: Any):
7272
'No sessions will be sent to Bugsnag.')
7373
self.sent_session_warning = True
7474
else:
75-
options = {
76-
'endpoint': config.session_endpoint,
77-
'success': 202,
78-
}
75+
if options is None:
76+
options = {}
77+
78+
options['endpoint'] = config.session_endpoint
79+
options['success'] = 202
80+
7981
self.deliver(config, payload, options)
8082

8183
def queue_request(self, request: Callable, config, options: Dict):
@@ -96,8 +98,9 @@ def safe_request():
9698

9799

98100
class UrllibDelivery(Delivery):
99-
100-
def deliver(self, config, payload: Any, options={}):
101+
def deliver(self, config, payload: Any, options=None):
102+
if options is None:
103+
options = {}
101104

102105
def request():
103106
uri = options.pop('endpoint', config.endpoint)
@@ -134,8 +137,9 @@ def request():
134137

135138

136139
class RequestsDelivery(Delivery):
137-
138-
def deliver(self, config, payload: Any, options={}):
140+
def deliver(self, config, payload: Any, options=None):
141+
if options is None:
142+
options = {}
139143

140144
def request():
141145
uri = options.pop('endpoint', config.endpoint)

bugsnag/notifier.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
_NOTIFIER_INFORMATION = {
22
'name': 'Python Bugsnag Notifier',
33
'url': 'https://github.com/bugsnag/bugsnag-python',
4-
'version': '4.6.1'
4+
'version': '4.6.2'
55
}

bugsnag/sessiontracker.py

+19-5
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def start_session(self):
5454
_session_info.set(new_session)
5555
self.__queue_session(start_time)
5656

57-
def send_sessions(self):
57+
def send_sessions(self, asynchronous=True):
5858
self.mutex.acquire()
5959
try:
6060
sessions = []
@@ -66,7 +66,8 @@ def send_sessions(self):
6666
self.session_counts = {}
6767
finally:
6868
self.mutex.release()
69-
self.__deliver(sessions)
69+
70+
self.__deliver(sessions, asynchronous)
7071

7172
def __start_delivery(self):
7273
if self.delivery_thread is None:
@@ -83,7 +84,8 @@ def deliver():
8384
def cleanup():
8485
if self.delivery_thread is not None:
8586
self.delivery_thread.cancel()
86-
self.send_sessions()
87+
88+
self.send_sessions(asynchronous=False)
8789

8890
atexit.register(cleanup)
8991

@@ -96,7 +98,7 @@ def __queue_session(self, start_time: str):
9698
finally:
9799
self.mutex.release()
98100

99-
def __deliver(self, sessions: List[Dict]):
101+
def __deliver(self, sessions: List[Dict], asynchronous=True):
100102
if not sessions:
101103
self.config.logger.debug("No sessions to deliver")
102104
return
@@ -132,7 +134,19 @@ def __deliver(self, sessions: List[Dict]):
132134
)
133135

134136
encoded_payload = encoder.encode(payload)
135-
self.config.delivery.deliver_sessions(self.config, encoded_payload)
137+
138+
deliver = self.config.delivery.deliver_sessions
139+
140+
if 'options' in deliver.__code__.co_varnames:
141+
deliver(
142+
self.config,
143+
encoded_payload,
144+
options={'asynchronous': asynchronous}
145+
)
146+
else:
147+
deliver(self.config, encoded_payload)
148+
149+
136150
except Exception as e:
137151
self.config.logger.exception('Sending sessions failed %s', e)
138152

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
setup(
1616
name='bugsnag',
17-
version='4.6.1',
17+
version='4.6.2',
1818
description='Automatic error monitoring for django, flask, etc.',
1919
long_description=__doc__,
2020
author='Simon Maynard',

tests/integrations/test_asgi.py

-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ async def app(scope, recv, send):
139139
self.assertEqual('GET', request['httpMethod'])
140140
self.assertEqual('http', request['type'])
141141
self.assertEqual('http://testserver/', request['url'])
142-
self.assertEqual('testclient', request['clientIp'])
143142
self.assertEqual('testclient', request['headers']['user-agent'])
144143

145144
exception = payload['events'][0]['exceptions'][0]

tests/test_configuration.py

+21
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ class BadDelivery(object):
195195
def deliv(self, *args, **kwargs):
196196
pass
197197

198+
class OkDelivery:
199+
def deliver(self, *args, **kwargs):
200+
pass
201+
202+
def deliver_sessions(self, config, payload):
203+
pass
204+
198205
class GoodDelivery(object):
199206
def deliver(self, *args, **kwargs):
200207
pass
@@ -213,6 +220,20 @@ def deliver(self, *args, **kwargs):
213220
assert len(record) == 1
214221
assert c.delivery == good
215222

223+
with pytest.warns(DeprecationWarning) as record:
224+
ok = OkDelivery()
225+
226+
c.configure(delivery=ok)
227+
228+
assert len(record) == 1
229+
assert str(record[0].message) == (
230+
'delivery.deliver_sessions should accept an "options" ' +
231+
'parameter to allow for synchronous delivery, sessions ' +
232+
'may be lost when the process exits'
233+
)
234+
235+
assert c.delivery == ok
236+
216237
def test_validate_hostname(self):
217238
c = Configuration()
218239
with pytest.warns(RuntimeWarning) as record:

0 commit comments

Comments
 (0)