Skip to content

Commit 2e75f79

Browse files
committed
Added tests for testing correct sampling_context given to start_transaction by AWS integration.
1 parent 8cbdfa8 commit 2e75f79

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Need to add some ignore rules in this directory, because the unit tests will add the Sentry SDK and its dependencies
2+
# into this directory to create a Lambda function package that contains everything needed to instrument a Lambda function using Sentry.
3+
4+
# Ignore everything
5+
*
6+
7+
# But not index.py
8+
!index.py
9+
10+
# And not .gitignore itself
11+
!.gitignore
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import json
2+
import os
3+
import sentry_sdk
4+
from sentry_sdk.integrations.aws_lambda import AwsLambdaIntegration
5+
6+
# Global variables to store sampling context for verification
7+
sampling_context_data = {
8+
"aws_event_present": False,
9+
"aws_context_present": False,
10+
"event_data": None,
11+
}
12+
13+
14+
def trace_sampler(sampling_context):
15+
# Store the sampling context for verification
16+
global sampling_context_data
17+
18+
# Check if aws_event and aws_context are in the sampling_context
19+
if "aws_event" in sampling_context:
20+
sampling_context_data["aws_event_present"] = True
21+
sampling_context_data["event_data"] = sampling_context["aws_event"]
22+
23+
if "aws_context" in sampling_context:
24+
sampling_context_data["aws_context_present"] = True
25+
26+
print("Sampling context data:", sampling_context_data)
27+
return 1.0 # Always sample
28+
29+
30+
sentry_sdk.init(
31+
dsn=os.environ.get("SENTRY_DSN"),
32+
traces_sample_rate=1.0,
33+
traces_sampler=trace_sampler,
34+
integrations=[AwsLambdaIntegration()],
35+
)
36+
37+
38+
def handler(event, context):
39+
# Return the sampling context data for verification
40+
return {
41+
"statusCode": 200,
42+
"body": json.dumps(
43+
{
44+
"message": "Hello from Lambda with embedded Sentry SDK!",
45+
"event": event,
46+
"sampling_context_data": sampling_context_data,
47+
}
48+
),
49+
}

tests/integrations/aws_lambda/test_aws_lambda.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,22 @@ def test_span_origin(lambda_client, test_environment):
450450
assert (
451451
transaction_event["contexts"]["trace"]["origin"] == "auto.function.aws_lambda"
452452
)
453+
454+
455+
def test_traces_sampler_has_correct_sampling_context(lambda_client, test_environment):
456+
"""
457+
Test that aws_event and aws_context are passed in the custom_sampling_context
458+
when using the AWS Lambda integration.
459+
"""
460+
test_payload = {"test_key": "test_value"}
461+
response = lambda_client.invoke(
462+
FunctionName="TracesSampler",
463+
Payload=json.dumps(test_payload),
464+
)
465+
response_payload = json.loads(response["Payload"].read().decode())
466+
sampling_context_data = json.loads(response_payload["body"])[
467+
"sampling_context_data"
468+
]
469+
assert sampling_context_data.get("aws_event_present") is True
470+
assert sampling_context_data.get("aws_context_present") is True
471+
assert sampling_context_data.get("event_data", {}).get("test_key") == "test_value"

tests/integrations/aws_lambda/utils.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import gzip
22
import json
33
import os
4+
import shutil
5+
import subprocess
46
import requests
57
import sys
68
import time
@@ -20,6 +22,9 @@
2022

2123

2224
LAMBDA_FUNCTION_DIR = "./tests/integrations/aws_lambda/lambda_functions/"
25+
LAMBDA_FUNCTION_WITH_EMBEDDED_SDK_DIR = (
26+
"./tests/integrations/aws_lambda/lambda_functions_with_embedded_sdk/"
27+
)
2328
LAMBDA_FUNCTION_TIMEOUT = 10
2429
SAM_PORT = 3001
2530

@@ -47,6 +52,20 @@ def get_host_ip():
4752
return host
4853

4954

55+
def get_project_root():
56+
"""
57+
Returns the absolute path to the project root directory.
58+
"""
59+
# Start from the current file's directory
60+
current_dir = os.path.dirname(os.path.abspath(__file__))
61+
62+
# Navigate up to the project root (4 levels up from tests/integrations/aws_lambda/)
63+
# This is equivalent to the multiple dirname() calls
64+
project_root = os.path.abspath(os.path.join(current_dir, "../../../"))
65+
66+
return project_root
67+
68+
5069
class LocalLambdaStack(Stack):
5170
"""
5271
Uses the AWS CDK to create a local SAM stack containing Lambda functions.
@@ -124,6 +143,73 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
124143
)
125144
)
126145

146+
print(
147+
"[LocalLambdaStack] Add all Lambda functions defined in "
148+
"/tests/integrations/aws_lambda/lambda_functions_with_embedded_sdk/ to the SAM stack"
149+
)
150+
lambda_dirs = [
151+
d
152+
for d in os.listdir(LAMBDA_FUNCTION_WITH_EMBEDDED_SDK_DIR)
153+
if os.path.isdir(os.path.join(LAMBDA_FUNCTION_WITH_EMBEDDED_SDK_DIR, d))
154+
]
155+
for lambda_dir in lambda_dirs:
156+
# Copy the Sentry SDK into the function directory
157+
sdk_path = os.path.join(
158+
LAMBDA_FUNCTION_WITH_EMBEDDED_SDK_DIR, lambda_dir, "sentry_sdk"
159+
)
160+
if not os.path.exists(sdk_path):
161+
# Find the Sentry SDK in the current environment
162+
import sentry_sdk as sdk_module
163+
164+
sdk_source = os.path.dirname(sdk_module.__file__)
165+
shutil.copytree(sdk_source, sdk_path)
166+
167+
# Install the requirements of Sentry SDK into the function directory
168+
requirements_file = os.path.join(
169+
get_project_root(), "requirements-aws-lambda-layer.txt"
170+
)
171+
172+
# Install the package using pip
173+
subprocess.check_call(
174+
[
175+
sys.executable,
176+
"-m",
177+
"pip",
178+
"install",
179+
"--upgrade",
180+
"--target",
181+
os.path.join(LAMBDA_FUNCTION_WITH_EMBEDDED_SDK_DIR, lambda_dir),
182+
"-r",
183+
requirements_file,
184+
]
185+
)
186+
187+
CfnResource(
188+
self,
189+
lambda_dir,
190+
type="AWS::Serverless::Function",
191+
properties={
192+
"CodeUri": os.path.join(
193+
LAMBDA_FUNCTION_WITH_EMBEDDED_SDK_DIR, lambda_dir
194+
),
195+
"Handler": "index.handler",
196+
"Runtime": PYTHON_VERSION,
197+
"Timeout": LAMBDA_FUNCTION_TIMEOUT,
198+
"Environment": {
199+
"Variables": {
200+
"SENTRY_DSN": dsn,
201+
}
202+
},
203+
},
204+
)
205+
print(
206+
"[LocalLambdaStack] - Created Lambda function: %s (%s)"
207+
% (
208+
lambda_dir,
209+
os.path.join(LAMBDA_FUNCTION_DIR, lambda_dir),
210+
)
211+
)
212+
127213
@classmethod
128214
def wait_for_stack(cls, timeout=30, port=SAM_PORT):
129215
"""

0 commit comments

Comments
 (0)