@@ -383,6 +383,72 @@ def handler(event, context):
383
383
assert "test result" in result
384
384
385
385
386
+ def test_tracer_yield_from_context_manager_exception_metadata (mocker , provider_stub , in_subsegment_mock ):
387
+ # GIVEN tracer is initialized
388
+ provider = provider_stub (in_subsegment = in_subsegment_mock .in_subsegment )
389
+ tracer = Tracer (provider = provider , service = "booking" )
390
+
391
+ # WHEN capture_method decorator is used on a context manager
392
+ # and the method raises an exception
393
+ @tracer .capture_method
394
+ @contextlib .contextmanager
395
+ def yield_with_capture ():
396
+ yield "partial"
397
+ raise ValueError ("test" )
398
+
399
+ with pytest .raises (ValueError ):
400
+ with yield_with_capture () as partial_val :
401
+ assert partial_val == "partial"
402
+
403
+ # THEN we should add the exception using method name as key plus error
404
+ # and their service name as the namespace
405
+ put_metadata_mock_args = in_subsegment_mock .put_metadata .call_args [1 ]
406
+ assert put_metadata_mock_args ["key" ] == "yield_with_capture error"
407
+ assert isinstance (put_metadata_mock_args ["value" ], ValueError )
408
+ assert put_metadata_mock_args ["namespace" ] == "booking"
409
+
410
+
411
+ def test_tracer_yield_from_nested_context_manager (mocker , provider_stub , in_subsegment_mock ):
412
+ # GIVEN tracer is initialized
413
+ provider = provider_stub (in_subsegment = in_subsegment_mock .in_subsegment )
414
+ tracer = Tracer (provider = provider , service = "booking" )
415
+
416
+ # WHEN capture_method decorator is used on a context manager nesting another context manager
417
+ class NestedContextManager (object ):
418
+ def __enter__ (self ):
419
+ self ._value = {"result" : "test result" }
420
+ return self ._value
421
+
422
+ def __exit__ (self , exc_type , exc_val , exc_tb ):
423
+ self ._value ["result" ] = "exit was called before yielding"
424
+
425
+ @tracer .capture_method
426
+ @contextlib .contextmanager
427
+ def yield_with_capture ():
428
+ with NestedContextManager () as nested_context :
429
+ yield nested_context
430
+
431
+ @tracer .capture_lambda_handler
432
+ def handler (event , context ):
433
+ response = []
434
+ with yield_with_capture () as yielded_value :
435
+ response .append (yielded_value ["result" ])
436
+
437
+ return response
438
+
439
+ result = handler ({}, {})
440
+
441
+ # THEN we should have a subsegment named after the method name
442
+ # and add its response as trace metadata
443
+ handler_trace , yield_function_trace = in_subsegment_mock .in_subsegment .call_args_list
444
+
445
+ assert "test result" in in_subsegment_mock .put_metadata .call_args [1 ]["value" ]
446
+ assert in_subsegment_mock .in_subsegment .call_count == 2
447
+ assert handler_trace == mocker .call (name = "## handler" )
448
+ assert yield_function_trace == mocker .call (name = "## yield_with_capture" )
449
+ assert "test result" in result
450
+
451
+
386
452
def test_tracer_yield_from_generator (mocker , provider_stub , in_subsegment_mock ):
387
453
# GIVEN tracer is initialized
388
454
provider = provider_stub (in_subsegment = in_subsegment_mock .in_subsegment )
@@ -411,3 +477,28 @@ def handler(event, context):
411
477
assert handler_trace == mocker .call (name = "## handler" )
412
478
assert generator_fn_trace == mocker .call (name = "## generator_fn" )
413
479
assert "test result" in result
480
+
481
+
482
+ def test_tracer_yield_from_generator_exception_metadata (mocker , provider_stub , in_subsegment_mock ):
483
+ # GIVEN tracer is initialized
484
+ provider = provider_stub (in_subsegment = in_subsegment_mock .in_subsegment )
485
+ tracer = Tracer (provider = provider , service = "booking" )
486
+
487
+ # WHEN capture_method decorator is used on a generator function
488
+ # and the method raises an exception
489
+ @tracer .capture_method
490
+ def generator_fn ():
491
+ yield "partial"
492
+ raise ValueError ("test" )
493
+
494
+ with pytest .raises (ValueError ):
495
+ gen = generator_fn ()
496
+ list (gen )
497
+
498
+ # THEN we should add the exception using method name as key plus error
499
+ # and their service name as the namespace
500
+ put_metadata_mock_args = in_subsegment_mock .put_metadata .call_args [1 ]
501
+ assert put_metadata_mock_args ["key" ] == "generator_fn error"
502
+ assert put_metadata_mock_args ["namespace" ] == "booking"
503
+ assert isinstance (put_metadata_mock_args ["value" ], ValueError )
504
+ assert str (put_metadata_mock_args ["value" ]) == "test"
0 commit comments