Skip to content

Commit 9513133

Browse files
feat(capture_method): addressing PR feedback
1 parent 19de9dd commit 9513133

File tree

4 files changed

+41
-27
lines changed

4 files changed

+41
-27
lines changed

aws_lambda_powertools/tracing/tracer.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ def capture_method(
354354
"""Decorator to create subsegment for arbitrary functions
355355
356356
It also captures both response and exceptions as metadata
357-
and creates a subsegment named `## <method_name>`
357+
and creates a subsegment named `## <method_module.method_qualifiedname>`
358+
# see here: [Qualified name for classes and functions](https://peps.python.org/pep-3155/)
358359
359360
When running [async functions concurrently](https://docs.python.org/3/library/asyncio-task.html#id6),
360361
methods may impact each others subsegment, and can trigger

tests/e2e/tracer/handlers/same_function_name.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from abc import ABC, abstractmethod
12
from uuid import uuid4
23

34
from aws_lambda_powertools import Tracer
@@ -6,13 +7,22 @@
67
tracer = Tracer()
78

89

9-
class Comments:
10+
class MainAbstractClass(ABC):
11+
def __init__(self):
12+
super().__init__()
13+
14+
@abstractmethod
15+
def get_all(self):
16+
raise NotImplementedError
17+
18+
19+
class Comments(MainAbstractClass):
1020
@tracer.capture_method
1121
def get_all(self):
1222
return [{"id": f"{uuid4()}", "completed": False} for _ in range(5)]
1323

1424

15-
class Todos:
25+
class Todos(MainAbstractClass):
1626
@tracer.capture_method
1727
def get_all(self):
1828
return [{"id": f"{uuid4()}", "completed": False} for _ in range(5)]

tests/e2e/tracer/test_tracer.py

+10-11
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,26 @@ def test_lambda_handler_trace_is_visible(basic_handler_fn_arn: str, basic_handle
6363

6464
def test_lambda_handler_trace_multiple_functions_same_name(same_function_name_arn: str, same_function_name_fn: str):
6565
# GIVEN
66-
method_name_1 = "same_function_name.Todos.get_all"
67-
method_subsegment_1 = f"## {method_name_1}"
68-
method_metadata_key_1 = f"{method_name_1} response"
66+
method_name_todos = "same_function_name.Todos.get_all"
67+
method_subsegment_todos = f"## {method_name_todos}"
68+
method_metadata_key_todos = f"{method_name_todos} response"
6969

70-
method_name_2 = "same_function_name.Comments.get_all"
71-
method_subsegment_2 = f"## {method_name_2}"
72-
method_metadata_key_2 = f"{method_name_2} response"
70+
method_name_comments = "same_function_name.Comments.get_all"
71+
method_subsegment_comments = f"## {method_name_comments}"
72+
method_metadata_key_comments = f"{method_name_comments} response"
7373

7474
trace_query = data_builder.build_trace_default_query(function_name=same_function_name_fn)
7575

7676
# WHEN
7777
_, execution_time = data_fetcher.get_lambda_response(lambda_arn=same_function_name_arn)
78-
data_fetcher.get_lambda_response(lambda_arn=same_function_name_arn)
7978

8079
# THEN
8180
trace = data_fetcher.get_traces(start_date=execution_time, filter_expression=trace_query)
8281

83-
assert len(trace.get_metadata(key=method_metadata_key_1, namespace=TracerStack.SERVICE_NAME)) == 1
84-
assert len(trace.get_metadata(key=method_metadata_key_2, namespace=TracerStack.SERVICE_NAME)) == 1
85-
assert len(trace.get_subsegment(name=method_subsegment_1)) == 1
86-
assert len(trace.get_subsegment(name=method_subsegment_2)) == 1
82+
assert len(trace.get_metadata(key=method_metadata_key_todos, namespace=TracerStack.SERVICE_NAME)) == 1
83+
assert len(trace.get_metadata(key=method_metadata_key_comments, namespace=TracerStack.SERVICE_NAME)) == 1
84+
assert len(trace.get_subsegment(name=method_subsegment_todos)) == 1
85+
assert len(trace.get_subsegment(name=method_subsegment_comments)) == 1
8786

8887

8988
def test_async_trace_is_visible(async_fn_arn: str, async_fn: str):

tests/unit/test_tracing.py

+17-13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
# Maintenance: This should move to Functional tests and use Fake over mocks.
1212

13+
__MODULE_PREFIX__ = "unit.test_tracing"
14+
1315

1416
@pytest.fixture
1517
def dummy_response():
@@ -126,10 +128,12 @@ def greeting(name, message):
126128
# and use service name as a metadata namespace
127129
assert in_subsegment_mock.in_subsegment.call_count == 1
128130
assert in_subsegment_mock.in_subsegment.call_args == mocker.call(
129-
name="## unit.test_tracing.test_tracer_method.<locals>.greeting"
131+
name=f"## {__MODULE_PREFIX__}.test_tracer_method.<locals>.greeting"
130132
)
131133
assert in_subsegment_mock.put_metadata.call_args == mocker.call(
132-
key="unit.test_tracing.test_tracer_method.<locals>.greeting response", value=dummy_response, namespace="booking"
134+
key=f"{__MODULE_PREFIX__}.test_tracer_method.<locals>.greeting response",
135+
value=dummy_response,
136+
namespace="booking",
133137
)
134138

135139

@@ -257,7 +261,7 @@ def greeting(name, message):
257261
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
258262
assert (
259263
put_metadata_mock_args["key"]
260-
== "unit.test_tracing.test_tracer_method_exception_metadata.<locals>.greeting error"
264+
== f"{__MODULE_PREFIX__}.test_tracer_method_exception_metadata.<locals>.greeting error"
261265
)
262266
assert put_metadata_mock_args["namespace"] == "booking"
263267

@@ -311,20 +315,20 @@ async def greeting(name, message):
311315
# THEN we should add metadata for each response like we would for a sync decorated method
312316
assert in_subsegment_mock.in_subsegment.call_count == 2
313317
assert in_subsegment_greeting_call_args == mocker.call(
314-
name="## unit.test_tracing.test_tracer_method_nested_async.<locals>.greeting"
318+
name=f"## {__MODULE_PREFIX__}.test_tracer_method_nested_async.<locals>.greeting"
315319
)
316320
assert in_subsegment_greeting2_call_args == mocker.call(
317-
name="## unit.test_tracing.test_tracer_method_nested_async.<locals>.greeting_2"
321+
name=f"## {__MODULE_PREFIX__}.test_tracer_method_nested_async.<locals>.greeting_2"
318322
)
319323

320324
assert in_subsegment_mock.put_metadata.call_count == 2
321325
assert put_metadata_greeting2_call_args == mocker.call(
322-
key="unit.test_tracing.test_tracer_method_nested_async.<locals>.greeting_2 response",
326+
key=f"{__MODULE_PREFIX__}.test_tracer_method_nested_async.<locals>.greeting_2 response",
323327
value=dummy_response,
324328
namespace="booking",
325329
)
326330
assert put_metadata_greeting_call_args == mocker.call(
327-
key="unit.test_tracing.test_tracer_method_nested_async.<locals>.greeting response",
331+
key=f"{__MODULE_PREFIX__}.test_tracer_method_nested_async.<locals>.greeting response",
328332
value=dummy_response,
329333
namespace="booking",
330334
)
@@ -370,7 +374,7 @@ async def greeting(name, message):
370374
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
371375
assert (
372376
put_metadata_mock_args["key"]
373-
== "unit.test_tracing.test_tracer_method_exception_metadata_async.<locals>.greeting error"
377+
== f"{__MODULE_PREFIX__}.test_tracer_method_exception_metadata_async.<locals>.greeting error"
374378
)
375379
assert put_metadata_mock_args["namespace"] == "booking"
376380

@@ -404,7 +408,7 @@ def handler(event, context):
404408
assert in_subsegment_mock.in_subsegment.call_count == 2
405409
assert handler_trace == mocker.call(name="## handler")
406410
assert yield_function_trace == mocker.call(
407-
name="## unit.test_tracing.test_tracer_yield_from_context_manager.<locals>.yield_with_capture"
411+
name=f"## {__MODULE_PREFIX__}.test_tracer_yield_from_context_manager.<locals>.yield_with_capture"
408412
)
409413
assert "test result" in result
410414

@@ -431,7 +435,7 @@ def yield_with_capture():
431435
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
432436
assert (
433437
put_metadata_mock_args["key"]
434-
== "unit.test_tracing.test_tracer_yield_from_context_manager_exception_metadata.<locals>.yield_with_capture error" # noqa E501
438+
== f"{__MODULE_PREFIX__}.test_tracer_yield_from_context_manager_exception_metadata.<locals>.yield_with_capture error" # noqa E501
435439
)
436440
assert isinstance(put_metadata_mock_args["value"], ValueError)
437441
assert put_metadata_mock_args["namespace"] == "booking"
@@ -475,7 +479,7 @@ def handler(event, context):
475479
assert in_subsegment_mock.in_subsegment.call_count == 2
476480
assert handler_trace == mocker.call(name="## handler")
477481
assert yield_function_trace == mocker.call(
478-
name="## unit.test_tracing.test_tracer_yield_from_nested_context_manager.<locals>.yield_with_capture"
482+
name=f"## {__MODULE_PREFIX__}.test_tracer_yield_from_nested_context_manager.<locals>.yield_with_capture"
479483
)
480484
assert "test result" in result
481485

@@ -507,7 +511,7 @@ def handler(event, context):
507511
assert in_subsegment_mock.in_subsegment.call_count == 2
508512
assert handler_trace == mocker.call(name="## handler")
509513
assert generator_fn_trace == mocker.call(
510-
name="## unit.test_tracing.test_tracer_yield_from_generator.<locals>.generator_fn"
514+
name=f"## {__MODULE_PREFIX__}.test_tracer_yield_from_generator.<locals>.generator_fn"
511515
)
512516
assert "test result" in result
513517

@@ -533,7 +537,7 @@ def generator_fn():
533537
put_metadata_mock_args = in_subsegment_mock.put_metadata.call_args[1]
534538
assert (
535539
put_metadata_mock_args["key"]
536-
== "unit.test_tracing.test_tracer_yield_from_generator_exception_metadata.<locals>.generator_fn error"
540+
== f"{__MODULE_PREFIX__}.test_tracer_yield_from_generator_exception_metadata.<locals>.generator_fn error"
537541
)
538542
assert put_metadata_mock_args["namespace"] == "booking"
539543
assert isinstance(put_metadata_mock_args["value"], ValueError)

0 commit comments

Comments
 (0)