Skip to content

Commit a81a90f

Browse files
authored
Add lambda url granularity to lambda integration (#1609)
* Add lambda url granularity to lambda integration * CHANGELOG
1 parent d954516 commit a81a90f

File tree

4 files changed

+96
-6
lines changed

4 files changed

+96
-6
lines changed

CHANGELOG.asciidoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ endif::[]
2929
//===== Bug fixes
3030
//
3131
32+
=== Unreleased
33+
34+
// Unreleased changes go here
35+
// When the next release happens, nest these changes under the "Python Agent version 6.x" heading
36+
//[float]
37+
//===== Features
38+
//
39+
[float]
40+
===== Bug fixes
41+
42+
* Differentiate Lambda URLs from API Gateway in AWS Lambda integration {pull}#1609[#1609]
43+
3244
3345
3446
[[release-notes-6.x]]

elasticapm/contrib/serverless/aws.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ def set_metadata_and_context(self, coldstart: bool) -> None:
254254
service_context["origin"]["version"] = self.event.get("version", "1.0")
255255
cloud_context["origin"] = {}
256256
cloud_context["origin"]["service"] = {"name": "api gateway"}
257+
if ".lambda-url." in self.event["requestContext"]["domainName"]:
258+
cloud_context["origin"]["service"]["name"] = "lambda url"
257259
cloud_context["origin"]["account"] = {"id": self.event["requestContext"]["accountId"]}
258260
cloud_context["origin"]["provider"] = "aws"
259261
elif self.source == "elb":
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"version": "2.0",
3+
"routeKey": "ANY /fetch_all",
4+
"rawPath": "/dev/fetch_all",
5+
"rawQueryString": "",
6+
"headers": {
7+
"accept": "*/*",
8+
"content-length": "0",
9+
"host": "myurl.lambda-url.us-west-2.on.aws",
10+
"user-agent": "curl/7.64.1",
11+
"x-amzn-trace-id": "Root=1-618018c5-763ade2b18f5734547c93e98",
12+
"x-forwarded-for": "67.171.184.49",
13+
"x-forwarded-port": "443",
14+
"x-forwarded-proto": "https"
15+
},
16+
"requestContext": {
17+
"accountId": "627286350134",
18+
"apiId": "02plqthge2",
19+
"domainName": "myurl.lambda-url.us-west-2.on.aws",
20+
"domainPrefix": "02plqthge2",
21+
"http": {
22+
"method": "GET",
23+
"path": "/dev/fetch_all",
24+
"protocol": "HTTP/1.1",
25+
"sourceIp": "67.171.184.49",
26+
"userAgent": "curl/7.64.1"
27+
},
28+
"requestId": "IIjO5hs7PHcEPIA=",
29+
"routeKey": "ANY /fetch_all",
30+
"stage": "dev",
31+
"time": "01/Nov/2021:16:41:41 +0000",
32+
"timeEpoch": 1635784901594
33+
},
34+
"isBase64Encoded": false
35+
}

tests/contrib/serverless/aws_tests.py

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ def event_api2():
5353
return json.load(f)
5454

5555

56+
@pytest.fixture
57+
def event_lurl():
58+
aws_data_file = os.path.join(os.path.dirname(__file__), "aws_lurl_test_data.json")
59+
with open(aws_data_file) as f:
60+
return json.load(f)
61+
62+
5663
@pytest.fixture
5764
def event_elb():
5865
aws_data_file = os.path.join(os.path.dirname(__file__), "aws_elb_test_data.json")
@@ -107,7 +114,10 @@ def test_request_data(event_api, event_api2):
107114
data = get_data_from_request(event_api, capture_body=True, capture_headers=True)
108115

109116
assert data["method"] == "GET"
110-
assert data["url"]["full"] == "https://02plqthge2.execute-api.us-east-1.amazonaws.com/dev/fetch_all?test%40key=test%40value"
117+
assert (
118+
data["url"]["full"]
119+
== "https://02plqthge2.execute-api.us-east-1.amazonaws.com/dev/fetch_all?test%40key=test%40value"
120+
)
111121
assert data["headers"]["Host"] == "02plqthge2.execute-api.us-east-1.amazonaws.com"
112122

113123
data = get_data_from_request(event_api2, capture_body=True, capture_headers=True)
@@ -119,24 +129,31 @@ def test_request_data(event_api, event_api2):
119129
data = get_data_from_request(event_api, capture_body=False, capture_headers=False)
120130

121131
assert data["method"] == "GET"
122-
assert data["url"]["full"] == "https://02plqthge2.execute-api.us-east-1.amazonaws.com/dev/fetch_all?test%40key=test%40value"
132+
assert (
133+
data["url"]["full"]
134+
== "https://02plqthge2.execute-api.us-east-1.amazonaws.com/dev/fetch_all?test%40key=test%40value"
135+
)
123136
assert "headers" not in data
124137

125138

126139
def test_elb_request_data(event_elb):
127140
data = get_data_from_request(event_elb, capture_body=True, capture_headers=True)
128141

129142
assert data["method"] == "POST"
130-
assert data["url"][
131-
"full"] == "https://blabla.com/toolz/api/v2.0/downloadPDF/PDF_2020-09-11_11-06-01.pdf?test%40key=test%40value&language=en-DE"
143+
assert (
144+
data["url"]["full"]
145+
== "https://blabla.com/toolz/api/v2.0/downloadPDF/PDF_2020-09-11_11-06-01.pdf?test%40key=test%40value&language=en-DE"
146+
)
132147
assert data["headers"]["host"] == "blabla.com"
133148
assert data["body"] == "blablablabody"
134149

135150
data = get_data_from_request(event_elb, capture_body=False, capture_headers=False)
136151

137152
assert data["method"] == "POST"
138-
assert data["url"][
139-
"full"] == "https://blabla.com/toolz/api/v2.0/downloadPDF/PDF_2020-09-11_11-06-01.pdf?test%40key=test%40value&language=en-DE"
153+
assert (
154+
data["url"]["full"]
155+
== "https://blabla.com/toolz/api/v2.0/downloadPDF/PDF_2020-09-11_11-06-01.pdf?test%40key=test%40value&language=en-DE"
156+
)
140157
assert "headers" not in data
141158
assert data["body"] == "[REDACTED]"
142159

@@ -202,6 +219,30 @@ def test_func(event, context):
202219
assert transaction["context"]["request"]["method"] == "GET"
203220
assert transaction["context"]["request"]["headers"]
204221
assert transaction["context"]["response"]["status_code"] == 200
222+
assert transaction["context"]["cloud"]["origin"]["service"]["name"] == "api gateway"
223+
224+
225+
def test_capture_serverless_lambda_url(event_lurl, context, elasticapm_client):
226+
os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
227+
228+
@capture_serverless(elasticapm_client=elasticapm_client)
229+
def test_func(event, context):
230+
with capture_span("test_span"):
231+
time.sleep(0.01)
232+
return {"statusCode": 200, "headers": {"foo": "bar"}}
233+
234+
test_func(event_lurl, context)
235+
236+
assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
237+
transaction = elasticapm_client.events[constants.TRANSACTION][0]
238+
239+
assert transaction["name"] == "GET /dev/fetch_all"
240+
assert transaction["result"] == "HTTP 2xx"
241+
assert transaction["span_count"]["started"] == 1
242+
assert transaction["context"]["request"]["method"] == "GET"
243+
assert transaction["context"]["request"]["headers"]
244+
assert transaction["context"]["response"]["status_code"] == 200
245+
assert transaction["context"]["cloud"]["origin"]["service"]["name"] == "lambda url"
205246

206247

207248
def test_capture_serverless_elb(event_elb, context, elasticapm_client):

0 commit comments

Comments
 (0)