Skip to content
This repository was archived by the owner on Aug 13, 2025. It is now read-only.

Commit 1a7706e

Browse files
authored
Capture exception details in AWS Lambda middleware. (#154)
Trace field names match the ones used in Tracer: beeline-python/beeline/trace.py ```python span.add_context({ "app.exception_type": str(type(e)), "app.exception_string": stringify_exception(e), "app.exception_stacktrace": traceback.format_exc(), }) ``` closes #153
1 parent a34c130 commit 1a7706e

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

beeline/middleware/awslambda/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import traceback
2+
13
import beeline
24
from beeline.propagation import Request
35
# In Lambda, a cold start is when Lambda has to spin up a new instance of a
@@ -146,6 +148,13 @@ def _beeline_wrapper(event, context):
146148
beeline.add_context_field('app.response', resp)
147149

148150
return resp
151+
except Exception as e:
152+
beeline.add_context({
153+
"app.exception_type": str(type(e)),
154+
"app.exception_string": beeline.internal.stringify_exception(e),
155+
"app.exception_stacktrace": traceback.format_exc(),
156+
})
157+
raise e
149158
finally:
150159
# This remains false for the lifetime of the module
151160
COLD_START = False

beeline/middleware/awslambda/test_awslambda.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,37 @@ def handler(event, context):
203203
'name': 'handler'}, ANY)
204204
m_add_context_field.assert_called_once_with('app.response', 1)
205205

206+
def test_handle_exceptions(self):
207+
''' ensure instrumentation occurs when the handler raises an exception '''
208+
with patch('beeline.propagate_and_start_trace') as m_propagate, \
209+
patch('beeline.add_context_field') as m_add_context_field, \
210+
patch('beeline.add_context') as m_add_context, \
211+
patch('beeline.middleware.awslambda.beeline._GBL'), \
212+
patch('beeline.middleware.awslambda.COLD_START') as m_cold_start:
213+
m_event = Mock()
214+
m_context = Mock(function_name='fn', function_version="1.1.1",
215+
aws_request_id='12345')
216+
217+
@awslambda.beeline_wrapper
218+
def handler(event, context):
219+
raise ValueError('something went wrong')
220+
221+
with self.assertRaises(ValueError):
222+
handler(m_event, m_context)
223+
224+
m_propagate.assert_called_once_with({
225+
'app.function_name': 'fn',
226+
'app.function_version': '1.1.1',
227+
'app.request_id': '12345',
228+
'app.event': ANY, # 'app.event' is included by default
229+
'meta.cold_start': ANY,
230+
'name': 'handler'}, ANY)
231+
m_add_context.assert_called_once_with({
232+
'app.exception_type': ANY, # representation changes between 2.7 and 3.x
233+
'app.exception_string': 'something went wrong',
234+
'app.exception_stacktrace': ANY
235+
})
236+
206237
def test_can_omit_input(self):
207238
''' ensure input event field can be omitted '''
208239
with patch('beeline.propagate_and_start_trace') as m_propagate, \

0 commit comments

Comments
 (0)