Skip to content

Commit 3923fc2

Browse files
author
Michal Ploski
committed
Create helper function for fetching trace metadata
1 parent be1a1bb commit 3923fc2

File tree

7 files changed

+79
-36
lines changed

7 files changed

+79
-36
lines changed

tests/e2e/logger/test_logger.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ def test_basic_lambda_no_debug_logs_visible(
6060
@pytest.mark.e2e
6161
def test_basic_lambda_contextual_data_logged(execute_lambda: conftest.InfrastructureOutput):
6262
# GIVEN
63-
6463
required_keys = (
6564
"xray_trace_id",
6665
"function_request_id",
@@ -127,7 +126,6 @@ def test_basic_lambda_empty_event_logged(execute_lambda: conftest.Infrastructure
127126
def test_no_context_lambda_contextual_data_not_logged(execute_lambda: conftest.InfrastructureOutput):
128127

129128
# GIVEN
130-
131129
required_missing_keys = (
132130
"function_request_id",
133131
"function_arn",

tests/e2e/metrics/handlers/basic_handler.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
from aws_lambda_powertools import Metrics
44
from aws_lambda_powertools.metrics import MetricUnit
55

6-
METRIC_NAMESPACE = os.environ["METRIC_NAMESPACE"]
76
METRIC_NAME = os.environ["METRIC_NAME"]
8-
SERVICE_NAME = os.environ["SERVICE_NAME"]
97

10-
metrics = Metrics(namespace=METRIC_NAMESPACE, service=SERVICE_NAME)
8+
metrics = Metrics()
119

1210

1311
@metrics.log_metrics

tests/e2e/metrics/test_metrics.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,30 @@ def config() -> conftest.LambdaConfig:
1313
return {
1414
"parameters": {},
1515
"environment_variables": {
16-
"METRIC_NAMESPACE": f"powertools-e2e-metric-{uuid.uuid4()}",
17-
"METRIC_NAME": "business-metric",
18-
"SERVICE_NAME": "test-powertools-service",
16+
"POWERTOOLS_METRICS_NAMESPACE": "powertools-e2e-metric",
17+
"POWERTOOLS_SERVICE_NAME": f"test-powertools-service",
18+
"METRIC_NAME": f"business-metric-{uuid.uuid4()}",
1919
},
2020
}
2121

2222

2323
@pytest.mark.e2e
2424
def test_basic_lambda_metric_visible(execute_lambda: conftest.InfrastructureOutput, config: conftest.LambdaConfig):
25+
# GIVEN
2526
start_date = execute_lambda.get_lambda_execution_time()
2627
end_date = start_date + datetime.timedelta(minutes=5)
2728

29+
# WHEN
2830
metrics = helpers.get_metrics(
2931
start_date=start_date,
3032
end_date=end_date,
31-
namespace=config["environment_variables"]["METRIC_NAMESPACE"],
33+
namespace=config["environment_variables"]["POWERTOOLS_METRICS_NAMESPACE"],
3234
metric_name=config["environment_variables"]["METRIC_NAME"],
33-
service_name=config["environment_variables"]["SERVICE_NAME"],
35+
service_name=config["environment_variables"]["POWERTOOLS_SERVICE_NAME"],
3436
cw_client=boto3.client(service_name="cloudwatch"),
3537
)
38+
39+
# THEN
3640
assert metrics["Timestamps"] and len(metrics["Timestamps"]) == 1
3741
assert metrics["Values"] and len(metrics["Values"]) == 1
3842
assert metrics["Values"][0] == 1
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
1+
import asyncio
12
import os
23

34
from aws_lambda_powertools import Tracer
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
46

5-
tracer = Tracer()
67
tracer = Tracer(service="e2e-tests-app")
78

89
ANNOTATION_KEY = os.environ["ANNOTATION_KEY"]
910
ANNOTATION_VALUE = os.environ["ANNOTATION_VALUE"]
11+
ANNOTATION_ASYNC_VALUE = os.environ["ANNOTATION_ASYNC_VALUE"]
1012

1113

1214
@tracer.capture_lambda_handler
13-
def lambda_handler(event, context):
14-
tracer.put_annotation(key=ANNOTATION_KEY, value=ANNOTATION_VALUE)
15+
def lambda_handler(event: dict, context: LambdaContext):
16+
# tracer.put_annotation(key=ANNOTATION_KEY, value=ANNOTATION_VALUE)
1517
tracer.put_metadata(key=ANNOTATION_KEY, value=ANNOTATION_VALUE)
18+
return asyncio.run(collect_payment())
19+
20+
21+
@tracer.capture_method
22+
async def collect_payment() -> str:
23+
# tracer.put_annotation(key=ANNOTATION_KEY, value=ANNOTATION_ASYNC_VALUE)
24+
tracer.put_metadata(key=ANNOTATION_KEY, value=ANNOTATION_ASYNC_VALUE)
1625
return "success"

tests/e2e/tracer/test_tracer.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,43 @@
1313
def config():
1414
return {
1515
"parameters": {"tracing": "ACTIVE"},
16-
"environment_variables": {"ANNOTATION_KEY": f"e2e-tracer-{uuid.uuid4()}", "ANNOTATION_VALUE": "stored"},
16+
"environment_variables": {
17+
"ANNOTATION_KEY": f"e2e-tracer-{uuid.uuid4()}",
18+
"ANNOTATION_VALUE": "stored",
19+
"ANNOTATION_ASYNC_VALUE": "payments",
20+
},
1721
}
1822

1923

2024
@pytest.mark.e2e
21-
def test_basic_lambda_trace_visible(execute_lambda: conftest.InfrastructureOutput, config: conftest.LambdaConfig):
25+
def test_basic_lambda_async_trace_visible(execute_lambda: conftest.InfrastructureOutput, config: conftest.LambdaConfig):
26+
# GIVEN
2227
lambda_arn = execute_lambda.get_lambda_arn(name="basichandlerarn")
2328
start_date = execute_lambda.get_lambda_execution_time()
2429
end_date = start_date + datetime.timedelta(minutes=5)
2530

31+
# WHEN
2632
trace = helpers.get_traces(
2733
start_date=start_date,
2834
end_date=end_date,
2935
lambda_function_name=lambda_arn.split(":")[-1],
3036
xray_client=boto3.client("xray"),
3137
)
3238

33-
for segment in trace["Traces"][0]["Segments"]:
34-
document = json.loads(segment["Document"])
35-
if document["origin"] == "AWS::Lambda::Function":
36-
for subsegment in document["subsegments"]:
37-
if subsegment["name"] == "Invocation":
38-
for x_subsegment in subsegment["subsegments"]:
39-
metadata = x_subsegment["metadata"]
40-
annotation = x_subsegment["annotations"]
39+
# THEN
40+
info = helpers.find_trace_additional_info(trace=trace)
41+
print(info)
42+
handler_trace_segment = [trace_segment for trace_segment in info if trace_segment.name == "## lambda_handler"][0]
43+
collect_payment_trace_segment = [
44+
trace_segment for trace_segment in info if trace_segment.name == "## collect_payment"
45+
][0]
4146

47+
assert handler_trace_segment.annotations["Service"] == "e2e-tests-app"
4248
assert (
43-
metadata["e2e-tests-app"][config["environment_variables"]["ANNOTATION_KEY"]]
49+
handler_trace_segment.metadata["e2e-tests-app"][config["environment_variables"]["ANNOTATION_KEY"]]
4450
== config["environment_variables"]["ANNOTATION_VALUE"]
4551
)
46-
assert annotation["Service"] == "e2e-tests-app"
52+
assert (
53+
collect_payment_trace_segment.metadata["e2e-tests-app"][config["environment_variables"]["ANNOTATION_KEY"]]
54+
== config["environment_variables"]["ANNOTATION_ASYNC_VALUE"]
55+
)

tests/e2e/utils/helpers.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
from datetime import datetime
33
from functools import lru_cache
4-
from typing import Any, List, Optional, Union
4+
from typing import Any, Dict, List, Optional, Union
55

66
from pydantic import BaseModel
77
from retry import retry
@@ -23,6 +23,12 @@ class Log(BaseModel):
2323
extra_info: Optional[str]
2424

2525

26+
class TraceSegment(BaseModel):
27+
name: str
28+
metadata: Dict = {}
29+
annotations: Dict = {}
30+
31+
2632
def trigger_lambda(lambda_arn: str, client: Any):
2733
response = client.invoke(FunctionName=lambda_arn, InvocationType="RequestResponse")
2834
return response
@@ -76,7 +82,7 @@ def get_metrics(
7682

7783

7884
@retry(ValueError, delay=1, jitter=1, tries=10)
79-
def get_traces(lambda_function_name: str, xray_client: Any, start_date: datetime, end_date: datetime):
85+
def get_traces(lambda_function_name: str, xray_client: Any, start_date: datetime, end_date: datetime) -> Dict:
8086
paginator = xray_client.get_paginator("get_trace_summaries")
8187
response_iterator = paginator.paginate(
8288
StartTime=start_date,
@@ -95,3 +101,27 @@ def get_traces(lambda_function_name: str, xray_client: Any, start_date: datetime
95101
)
96102

97103
return trace_details
104+
105+
106+
def find_trace_additional_info(trace: Dict) -> List[TraceSegment]:
107+
info = []
108+
for segment in trace["Traces"][0]["Segments"]:
109+
document = json.loads(segment["Document"])
110+
if document["origin"] == "AWS::Lambda::Function":
111+
for subsegment in document["subsegments"]:
112+
if subsegment["name"] == "Invocation":
113+
find_meta(segment=subsegment, result=info)
114+
return info
115+
116+
117+
def find_meta(segment: dict, result: List):
118+
for x_subsegment in segment["subsegments"]:
119+
result.append(
120+
TraceSegment(
121+
name=x_subsegment["name"],
122+
metadata=x_subsegment.get("metadata", {}),
123+
annotations=x_subsegment.get("annotations", {}),
124+
)
125+
)
126+
if x_subsegment.get("subsegments"):
127+
find_meta(segment=x_subsegment, result=result)

tests/e2e/utils/infrastructure.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ def _create_layer(self, stack: Stack):
5555
command=[
5656
"bash",
5757
"-c",
58-
f"export PYTHONPYCACHEPREFIX='/tmp/.cache/pycache/';\
59-
poetry export --with-credentials --format requirements.txt --output /tmp/requirements.txt &&\
58+
f"poetry export --with-credentials --format requirements.txt --output /tmp/requirements.txt &&\
6059
pip install -r /tmp/requirements.txt -t {output_dir} &&\
6160
cp -R {input_dir} {output_dir} &&\
62-
find {output_dir}/ -regex '^.*\\(__pycache__\\|\\.py[co]\\)$' -delete",
61+
find {output_dir}/ -regex '^.*__pycache__.*' -delete",
6362
],
6463
),
6564
),
@@ -155,15 +154,11 @@ def _upload_assets(self, template: dict, asset_root_dir: str):
155154
buf.seek(0)
156155
self.s3_client.upload_fileobj(Fileobj=buf, Bucket=bucket, Key=s3_key)
157156

158-
def _find_files(self, directory: str, only_py: bool = False) -> list:
157+
def _find_files(self, directory: str) -> list:
159158
file_paths = []
160159
for root, _, files in os.walk(directory):
161160
for filename in files:
162-
if only_py:
163-
if filename.endswith(".py"):
164-
file_paths.append(os.path.join(root, filename))
165-
else:
166-
file_paths.append(os.path.join(root, filename))
161+
file_paths.append(os.path.join(root, filename))
167162
return file_paths
168163

169164
def _deploy_stack(self, stack_name: str, template: dict):

0 commit comments

Comments
 (0)