Skip to content

Commit 40fec56

Browse files
committed
chore: cleanup tracer tests
1 parent 8469fe8 commit 40fec56

File tree

2 files changed

+84
-31
lines changed

2 files changed

+84
-31
lines changed

aws_lambda_powertools/tracing/tracer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,10 @@ def decorate(event, context):
269269
function_name=lambda_handler_name, data=response, subsegment=subsegment
270270
)
271271
except Exception as err:
272-
logger.exception("Exception received from lambda handler")
273-
self._add_full_exception_as_metadata(function_name=self.service, error=err, subsegment=subsegment)
272+
logger.exception(f"Exception received from {lambda_handler_name}")
273+
self._add_full_exception_as_metadata(
274+
function_name=lambda_handler_name, error=err, subsegment=subsegment
275+
)
274276
raise
275277

276278
return response

tests/unit/test_tracing.py

Lines changed: 80 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,20 @@ class In_subsegment(NamedTuple):
7979

8080

8181
def test_tracer_lambda_handler(mocker, dummy_response, provider_stub, in_subsegment_mock):
82+
# GIVEN Tracer is initialized with booking as the service name
8283
provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment)
8384
tracer = Tracer(provider=provider, service="booking")
8485

86+
# WHEN lambda_handler decorator is used
8587
@tracer.capture_lambda_handler
8688
def handler(event, context):
8789
return dummy_response
8890

8991
handler({}, mocker.MagicMock())
9092

93+
# THEN we should have a subsegment named handler
94+
# annotate cold start, and add its response as trace metadata
95+
# and use service name as a metadata namespace
9196
assert in_subsegment_mock.in_subsegment.call_count == 1
9297
assert in_subsegment_mock.in_subsegment.call_args == mocker.call(name="## handler")
9398
assert in_subsegment_mock.put_metadata.call_args == mocker.call(
@@ -98,141 +103,180 @@ def handler(event, context):
98103

99104

100105
def test_tracer_method(mocker, dummy_response, provider_stub, in_subsegment_mock):
106+
# GIVEN Tracer is initialized with booking as the service name
101107
provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment)
102-
Tracer(provider=provider, service="booking")
108+
tracer = Tracer(provider=provider, service="booking")
109+
110+
# WHEN capture_method decorator is used
111+
@tracer.capture_method
112+
def greeting(name, message):
113+
return dummy_response
114+
115+
greeting(name="Foo", message="Bar")
116+
117+
# THEN we should have a subsegment named after the method name
118+
# and add its response as trace metadata
119+
# and use service name as a metadata namespace
120+
assert in_subsegment_mock.in_subsegment.call_count == 1
121+
assert in_subsegment_mock.in_subsegment.call_args == mocker.call(name="## greeting")
122+
assert in_subsegment_mock.put_metadata.call_args == mocker.call(
123+
key="greeting response", value=dummy_response, namespace="booking"
124+
)
103125

104126

105127
def test_tracer_custom_metadata(mocker, dummy_response, provider_stub):
128+
# GIVEN Tracer is initialized with booking as the service name
106129
put_metadata_mock = mocker.MagicMock()
107-
annotation_key = "Booking response"
108-
annotation_value = {"bookingStatus": "CONFIRMED"}
109-
110130
provider = provider_stub(put_metadata_mock=put_metadata_mock)
111131
tracer = Tracer(provider=provider, service="booking")
132+
133+
# WHEN put_metadata is used
134+
annotation_key = "Booking response"
135+
annotation_value = {"bookingStatus": "CONFIRMED"}
112136
tracer.put_metadata(annotation_key, annotation_value)
113137

138+
# THEN we should have metadata expected and booking as namespace
114139
assert put_metadata_mock.call_count == 1
115140
assert put_metadata_mock.call_args_list[0] == mocker.call(
116141
key=annotation_key, value=annotation_value, namespace="booking"
117142
)
118143

119144

120145
def test_tracer_custom_annotation(mocker, dummy_response, provider_stub):
146+
# GIVEN Tracer is initialized
121147
put_annotation_mock = mocker.MagicMock()
122-
annotation_key = "BookingId"
123-
annotation_value = "123456"
124-
125148
provider = provider_stub(put_annotation_mock=put_annotation_mock)
126-
tracer = Tracer(provider=provider, service="booking")
149+
tracer = Tracer(provider=provider)
127150

151+
# WHEN put_metadata is used
152+
annotation_key = "BookingId"
153+
annotation_value = "123456"
128154
tracer.put_annotation(annotation_key, annotation_value)
129155

156+
# THEN we should have an annotation as expected
130157
assert put_annotation_mock.call_count == 1
131158
assert put_annotation_mock.call_args == mocker.call(key=annotation_key, value=annotation_value)
132159

133160

134161
@mock.patch("aws_lambda_powertools.tracing.Tracer.patch")
135162
def test_tracer_autopatch(patch_mock):
136-
# GIVEN tracer is instantiated
137-
# WHEN default options were used, or patch() was called
138-
# THEN tracer should patch all modules
163+
# GIVEN tracer is initialized
164+
# WHEN auto_patch hasn't been explicitly disabled
139165
Tracer(disabled=True)
166+
167+
# THEN tracer should patch all modules
140168
assert patch_mock.call_count == 1
141169

142170

143171
@mock.patch("aws_lambda_powertools.tracing.Tracer.patch")
144172
def test_tracer_no_autopatch(patch_mock):
145-
# GIVEN tracer is instantiated
173+
# GIVEN tracer is initialized
146174
# WHEN auto_patch is disabled
147-
# THEN tracer should not patch any module
148175
Tracer(disabled=True, auto_patch=False)
176+
177+
# THEN tracer should not patch any module
149178
assert patch_mock.call_count == 0
150179

151180

152-
def test_tracer_lambda_handler_empty_response_metadata(mocker, provider_stub):
181+
def test_tracer_lambda_handler_does_not_add_empty_response_as_metadata(mocker, provider_stub):
182+
# GIVEN tracer is initialized
153183
put_metadata_mock = mocker.MagicMock()
154184
provider = provider_stub(put_metadata_mock=put_metadata_mock)
155185
tracer = Tracer(provider=provider)
156186

187+
# WHEN capture_lambda_handler decorator is used
188+
# and the handler response is empty
157189
@tracer.capture_lambda_handler
158190
def handler(event, context):
159191
return
160192

161193
handler({}, mocker.MagicMock())
162194

195+
# THEN we should not add empty metadata
163196
assert put_metadata_mock.call_count == 0
164197

165198

166-
def test_tracer_method_empty_response_metadata(mocker, provider_stub):
199+
def test_tracer_method_does_not_add_empty_response_as_metadata(mocker, provider_stub):
200+
# GIVEN tracer is initialized
167201
put_metadata_mock = mocker.MagicMock()
168202
provider = provider_stub(put_metadata_mock=put_metadata_mock)
169203
tracer = Tracer(provider=provider)
170204

205+
# WHEN capture_method decorator is used
206+
# and the method response is empty
171207
@tracer.capture_method
172208
def greeting(name, message):
173209
return
174210

175211
greeting(name="Foo", message="Bar")
176212

213+
# THEN we should not add empty metadata
177214
assert put_metadata_mock.call_count == 0
178215

179216

180217
@mock.patch("aws_lambda_powertools.tracing.tracer.aws_xray_sdk.core.patch")
181-
@mock.patch("aws_lambda_powertools.tracing.tracer.aws_xray_sdk.core.patch_all")
182-
def test_tracer_patch(xray_patch_all_mock, xray_patch_mock, mocker):
183-
# GIVEN tracer is instantiated
184-
# WHEN default X-Ray provider client is mocked
185-
# THEN tracer should run just fine
186-
187-
Tracer()
188-
assert xray_patch_all_mock.call_count == 1
189-
218+
def test_tracer_patch_modules(xray_patch_mock, mocker):
219+
# GIVEN tracer is initialized with a list of modules to patch
190220
modules = ["boto3"]
221+
222+
# WHEN modules are supported by X-Ray
191223
Tracer(service="booking", patch_modules=modules)
192224

225+
# THEN tracer should run just fine
193226
assert xray_patch_mock.call_count == 1
194227
assert xray_patch_mock.call_args == mocker.call(modules)
195228

196229

197230
def test_tracer_method_exception_metadata(mocker, provider_stub, in_subsegment_mock):
198-
231+
# GIVEN tracer is initialized
199232
provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment)
200233
tracer = Tracer(provider=provider, service="booking")
201234

235+
# WHEN capture_method decorator is used
236+
# and the method raises an exception
202237
@tracer.capture_method
203238
def greeting(name, message):
204239
raise ValueError("test")
205240

206241
with pytest.raises(ValueError):
207242
greeting(name="Foo", message="Bar")
208243

244+
# THEN we should add the exception using method name as key plus error
245+
# and their service name as the namespace
209246
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
210247
assert put_metadata_mock_args["key"] == "greeting error"
211248
assert put_metadata_mock_args["namespace"] == "booking"
212249

213250

214251
def test_tracer_lambda_handler_exception_metadata(mocker, provider_stub, in_subsegment_mock):
215-
252+
# GIVEN tracer is initialized
216253
provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment)
217254
tracer = Tracer(provider=provider, service="booking")
218255

256+
# WHEN capture_lambda_handler decorator is used
257+
# and the method raises an exception
219258
@tracer.capture_lambda_handler
220259
def handler(event, context):
221260
raise ValueError("test")
222261

223262
with pytest.raises(ValueError):
224263
handler({}, mocker.MagicMock())
225264

265+
# THEN we should add the exception using handler name as key plus error
266+
# and their service name as the namespace
226267
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
227-
assert put_metadata_mock_args["key"] == "booking error"
268+
assert put_metadata_mock_args["key"] == "handler error"
269+
228270
assert put_metadata_mock_args["namespace"] == "booking"
229271

230272

231273
@pytest.mark.asyncio
232274
async def test_tracer_method_nested_async(mocker, dummy_response, provider_stub, in_subsegment_mock):
275+
# GIVEN tracer is initialized
233276
provider = provider_stub(in_subsegment_async=in_subsegment_mock.in_subsegment)
234277
tracer = Tracer(provider=provider, service="booking")
235278

279+
# WHEN capture_method decorator is used for nested async methods
236280
@tracer.capture_method
237281
async def greeting_2(name, message):
238282
return dummy_response
@@ -250,6 +294,7 @@ async def greeting(name, message):
250294
) = in_subsegment_mock.in_subsegment.call_args_list
251295
put_metadata_greeting2_call_args, put_metadata_greeting_call_args = in_subsegment_mock.put_metadata.call_args_list
252296

297+
# THEN we should add metadata for each response like we would for a sync decorated method
253298
assert in_subsegment_mock.in_subsegment.call_count == 2
254299
assert in_subsegment_greeting_call_args == mocker.call(name="## greeting")
255300
assert in_subsegment_greeting2_call_args == mocker.call(name="## greeting_2")
@@ -265,9 +310,10 @@ async def greeting(name, message):
265310

266311
@pytest.mark.asyncio
267312
async def test_tracer_method_nested_async_disabled(dummy_response):
268-
313+
# GIVEN tracer is initialized and explicitly disabled
269314
tracer = Tracer(service="booking", disabled=True)
270315

316+
# WHEN capture_method decorator is used
271317
@tracer.capture_method
272318
async def greeting_2(name, message):
273319
return dummy_response
@@ -277,23 +323,28 @@ async def greeting(name, message):
277323
await greeting_2(name, message)
278324
return dummy_response
279325

326+
# THEN we should run the decorator methods without side effects
280327
ret = await greeting(name="Foo", message="Bar")
281-
282328
assert ret == dummy_response
283329

284330

285331
@pytest.mark.asyncio
286332
async def test_tracer_method_exception_metadata_async(mocker, provider_stub, in_subsegment_mock):
333+
# GIVEN tracer is initialized
287334
provider = provider_stub(in_subsegment_async=in_subsegment_mock.in_subsegment)
288335
tracer = Tracer(provider=provider, service="booking")
289336

337+
# WHEN capture_method decorator is used in an async method
338+
# and the method raises an exception
290339
@tracer.capture_method
291340
async def greeting(name, message):
292341
raise ValueError("test")
293342

294343
with pytest.raises(ValueError):
295344
await greeting(name="Foo", message="Bar")
296345

346+
# THEN we should add the exception using method name as key plus error
347+
# and their service name as the namespace
297348
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
298349
assert put_metadata_mock_args["key"] == "greeting error"
299350
assert put_metadata_mock_args["namespace"] == "booking"

0 commit comments

Comments
 (0)