Skip to content

Commit 11d7c1b

Browse files
committed
Moved some stuff into utils file
1 parent e1d0c79 commit 11d7c1b

File tree

2 files changed

+151
-149
lines changed

2 files changed

+151
-149
lines changed
Lines changed: 3 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,17 @@
11
import boto3
2-
import gzip
32
import json
4-
import os
53
import pytest
6-
import requests
74
import subprocess
85
import time
9-
import threading
106
import yaml
117

12-
from aws_cdk import (
13-
App,
14-
CfnResource,
15-
Stack,
16-
)
17-
from constructs import Construct
18-
from fastapi import FastAPI, Request
19-
import uvicorn
8+
from aws_cdk import App
209

21-
from scripts.build_aws_lambda_layer import build_packaged_zip, DIST_PATH
10+
from .utils import DummyLambdaStack, SentryTestServer, SAM_PORT, SAM_REGION
2211

23-
24-
SAM_PORT = 3001
25-
SAM_REGION = "us-east-1"
2612
SAM_TEMPLATE_FILE = "sam.template.yaml"
2713

2814

29-
class DummyLambdaStack(Stack):
30-
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
31-
super().__init__(scope, construct_id, **kwargs)
32-
33-
# Override the template synthesis
34-
self.template_options.template_format_version = "2010-09-09"
35-
self.template_options.transforms = ["AWS::Serverless-2016-10-31"]
36-
37-
# Create Sentry Lambda Layer
38-
filename = "sentry-sdk-lambda-layer.zip"
39-
build_packaged_zip(
40-
make_dist=True,
41-
out_zip_filename=filename,
42-
)
43-
44-
layer = CfnResource(
45-
self,
46-
"SentryPythonServerlessSDK",
47-
type="AWS::Serverless::LayerVersion",
48-
properties={
49-
"ContentUri": os.path.join(DIST_PATH, filename),
50-
"CompatibleRuntimes": [
51-
"python3.7",
52-
"python3.8",
53-
"python3.9",
54-
"python3.10",
55-
"python3.11",
56-
"python3.12",
57-
"python3.13",
58-
],
59-
},
60-
)
61-
62-
# Add the function using SAM format
63-
CfnResource(
64-
self,
65-
"BasicTestFunction",
66-
type="AWS::Serverless::Function",
67-
properties={
68-
"CodeUri": "./tests/integrations/aws_lambda/lambda_functions/hello_world",
69-
"Handler": "sentry_sdk.integrations.init_serverless_sdk.sentry_lambda_handler",
70-
"Runtime": "python3.12",
71-
"Layers": [{"Ref": layer.logical_id}], # The layer adds the sentry-sdk
72-
"Environment": { # The environment variables are set up the Sentry SDK to instrument the lambda function
73-
"Variables": {
74-
"SENTRY_DSN": "http://[email protected]:9999/0",
75-
"SENTRY_INITIAL_HANDLER": "index.handler",
76-
"SENTRY_TRACES_SAMPLE_RATE": "1.0",
77-
}
78-
},
79-
},
80-
)
81-
82-
@classmethod
83-
def wait_for_stack(cls, timeout=30, port=SAM_PORT):
84-
"""
85-
Wait for SAM to be ready, with timeout.
86-
"""
87-
start_time = time.time()
88-
while True:
89-
if time.time() - start_time > timeout:
90-
raise TimeoutError(
91-
"SAM failed to start within {} seconds".format(timeout)
92-
)
93-
94-
try:
95-
# Try to connect to SAM
96-
response = requests.get(f"http://127.0.0.1:{port}/")
97-
if response.status_code == 200 or response.status_code == 404:
98-
return
99-
100-
except requests.exceptions.ConnectionError:
101-
time.sleep(1)
102-
continue
103-
104-
105-
class SentryTestServer:
106-
def __init__(self, port=9999):
107-
self.envelopes = []
108-
self.port = port
109-
self.app = FastAPI()
110-
111-
@self.app.post("/api/0/envelope/")
112-
async def envelope(request: Request):
113-
print("[SENTRY SERVER] Received envelope")
114-
try:
115-
raw_body = await request.body()
116-
except:
117-
return {"status": "no body"}
118-
119-
try:
120-
body = gzip.decompress(raw_body).decode("utf-8")
121-
except:
122-
# If decompression fails, assume it's plain text
123-
body = raw_body.decode("utf-8")
124-
125-
lines = body.split("\n")
126-
127-
current_line = 1 # line 0 is envelope header
128-
while current_line < len(lines):
129-
# skip empty lines
130-
if not lines[current_line].strip():
131-
current_line += 1
132-
continue
133-
134-
# skip envelope item header
135-
current_line += 1
136-
137-
# add envelope item to store
138-
envelope_item = lines[current_line]
139-
if envelope_item.strip():
140-
self.envelopes.append(json.loads(envelope_item))
141-
142-
return {"status": "ok"}
143-
144-
def run_server(self):
145-
uvicorn.run(self.app, host="0.0.0.0", port=self.port)
146-
147-
def start(self):
148-
print("[SENTRY SERVER] Starting server")
149-
server_thread = threading.Thread(target=self.run_server, daemon=True)
150-
server_thread.start()
151-
152-
def clear_envelopes(self):
153-
print("[SENTRY SERVER] Clear envelopes")
154-
self.envelopes = []
155-
156-
15715
@pytest.fixture(scope="session", autouse=True)
15816
def test_environment():
15917
print("Setting up AWS Lambda test infrastructure")
@@ -221,7 +79,7 @@ def clear_before_test(test_environment):
22179
@pytest.fixture
22280
def lambda_client():
22381
"""
224-
Create a boto3 client configured to use SAM local
82+
Create a boto3 client configured to use the local AWS SAM instance.
22583
"""
22684
return boto3.client(
22785
"lambda",
@@ -256,7 +114,3 @@ def test_basic_2(lambda_client, test_environment):
256114
message, transaction = test_environment["server"].envelopes
257115
assert message["message"] == "[SENTRY MESSAGE] Hello, Neel!"
258116
assert transaction["type"] == "transaction"
259-
260-
261-
# what is not working:
262-
# i should improve how the server are started and stopped at the beginning and end of the test session.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import gzip
2+
import json
3+
import os
4+
import requests
5+
import time
6+
import threading
7+
8+
from aws_cdk import (
9+
CfnResource,
10+
Stack,
11+
)
12+
from constructs import Construct
13+
from fastapi import FastAPI, Request
14+
import uvicorn
15+
16+
from scripts.build_aws_lambda_layer import build_packaged_zip, DIST_PATH
17+
18+
19+
SAM_PORT = 3001
20+
SAM_REGION = "us-east-1"
21+
22+
23+
class DummyLambdaStack(Stack):
24+
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
25+
super().__init__(scope, construct_id, **kwargs)
26+
27+
# Override the template synthesis
28+
self.template_options.template_format_version = "2010-09-09"
29+
self.template_options.transforms = ["AWS::Serverless-2016-10-31"]
30+
31+
# Create Sentry Lambda Layer
32+
filename = "sentry-sdk-lambda-layer.zip"
33+
build_packaged_zip(
34+
make_dist=True,
35+
out_zip_filename=filename,
36+
)
37+
38+
layer = CfnResource(
39+
self,
40+
"SentryPythonServerlessSDK",
41+
type="AWS::Serverless::LayerVersion",
42+
properties={
43+
"ContentUri": os.path.join(DIST_PATH, filename),
44+
"CompatibleRuntimes": [
45+
"python3.7",
46+
"python3.8",
47+
"python3.9",
48+
"python3.10",
49+
"python3.11",
50+
"python3.12",
51+
"python3.13",
52+
],
53+
},
54+
)
55+
56+
# Add the function using SAM format
57+
CfnResource(
58+
self,
59+
"BasicTestFunction",
60+
type="AWS::Serverless::Function",
61+
properties={
62+
"CodeUri": "./tests/integrations/aws_lambda/lambda_functions/hello_world",
63+
"Handler": "sentry_sdk.integrations.init_serverless_sdk.sentry_lambda_handler",
64+
"Runtime": "python3.12",
65+
"Layers": [{"Ref": layer.logical_id}], # The layer adds the sentry-sdk
66+
"Environment": { # The environment variables are set up the Sentry SDK to instrument the lambda function
67+
"Variables": {
68+
"SENTRY_DSN": "http://[email protected]:9999/0",
69+
"SENTRY_INITIAL_HANDLER": "index.handler",
70+
"SENTRY_TRACES_SAMPLE_RATE": "1.0",
71+
}
72+
},
73+
},
74+
)
75+
76+
@classmethod
77+
def wait_for_stack(cls, timeout=30, port=SAM_PORT):
78+
"""
79+
Wait for SAM to be ready, with timeout.
80+
"""
81+
start_time = time.time()
82+
while True:
83+
if time.time() - start_time > timeout:
84+
raise TimeoutError(
85+
"SAM failed to start within {} seconds".format(timeout)
86+
)
87+
88+
try:
89+
# Try to connect to SAM
90+
response = requests.get(f"http://127.0.0.1:{port}/")
91+
if response.status_code == 200 or response.status_code == 404:
92+
return
93+
94+
except requests.exceptions.ConnectionError:
95+
time.sleep(1)
96+
continue
97+
98+
99+
class SentryTestServer:
100+
def __init__(self, port=9999):
101+
self.envelopes = []
102+
self.port = port
103+
self.app = FastAPI()
104+
105+
@self.app.post("/api/0/envelope/")
106+
async def envelope(request: Request):
107+
print("[SENTRY SERVER] Received envelope")
108+
try:
109+
raw_body = await request.body()
110+
except:
111+
return {"status": "no body"}
112+
113+
try:
114+
body = gzip.decompress(raw_body).decode("utf-8")
115+
except:
116+
# If decompression fails, assume it's plain text
117+
body = raw_body.decode("utf-8")
118+
119+
lines = body.split("\n")
120+
121+
current_line = 1 # line 0 is envelope header
122+
while current_line < len(lines):
123+
# skip empty lines
124+
if not lines[current_line].strip():
125+
current_line += 1
126+
continue
127+
128+
# skip envelope item header
129+
current_line += 1
130+
131+
# add envelope item to store
132+
envelope_item = lines[current_line]
133+
if envelope_item.strip():
134+
self.envelopes.append(json.loads(envelope_item))
135+
136+
return {"status": "ok"}
137+
138+
def run_server(self):
139+
uvicorn.run(self.app, host="0.0.0.0", port=self.port)
140+
141+
def start(self):
142+
print("[SENTRY SERVER] Starting server")
143+
server_thread = threading.Thread(target=self.run_server, daemon=True)
144+
server_thread.start()
145+
146+
def clear_envelopes(self):
147+
print("[SENTRY SERVER] Clear envelopes")
148+
self.envelopes = []

0 commit comments

Comments
 (0)