@@ -35,6 +35,7 @@ class EventTypes(_stringTypedEnum):
35
35
CLOUDFRONT = "cloudfront"
36
36
DYNAMODB = "dynamodb"
37
37
KINESIS = "kinesis"
38
+ LAMBDA_FUNCTION_URL = "lambda-function-url"
38
39
S3 = "s3"
39
40
SNS = "sns"
40
41
SQS = "sqs"
@@ -115,6 +116,10 @@ def parse_event_source(event: dict) -> _EventSource:
115
116
116
117
request_context = event .get ("requestContext" )
117
118
if request_context and request_context .get ("stage" ):
119
+ if "domainName" in request_context and detect_lambda_function_url_domain (
120
+ request_context .get ("domainName" )
121
+ ):
122
+ return _EventSource (EventTypes .LAMBDA_FUNCTION_URL )
118
123
event_source = _EventSource (EventTypes .API_GATEWAY )
119
124
if "httpMethod" in event :
120
125
event_source .subtype = EventSubtypes .API_GATEWAY
@@ -160,6 +165,14 @@ def parse_event_source(event: dict) -> _EventSource:
160
165
return event_source
161
166
162
167
168
+ def detect_lambda_function_url_domain (domain : str ) -> bool :
169
+ # e.g. "etsn5fibjr.lambda-url.eu-south-1.amazonaws.com"
170
+ domain_parts = domain .split ("." )
171
+ if len (domain_parts ) < 2 :
172
+ return False
173
+ return domain_parts [1 ] == "lambda-url"
174
+
175
+
163
176
def parse_event_source_arn (source : _EventSource , event : dict , context : Any ) -> str :
164
177
"""
165
178
Parses the trigger event for an available ARN. If an ARN field is not provided
@@ -186,6 +199,18 @@ def parse_event_source_arn(source: _EventSource, event: dict, context: Any) -> s
186
199
aws_arn , account_id , distribution_id
187
200
)
188
201
202
+ # e.g. arn:aws:lambda:<region>:<account_id>:url:<function-name>:<function-qualifier>
203
+ if source .equals (EventTypes .LAMBDA_FUNCTION_URL ):
204
+ function_name = ""
205
+ if len (split_function_arn ) >= 7 :
206
+ function_name = split_function_arn [6 ]
207
+ function_arn = f"arn:aws:lambda:{ region } :{ account_id } :url:{ function_name } "
208
+ function_qualifier = ""
209
+ if len (split_function_arn ) >= 8 :
210
+ function_qualifier = split_function_arn [7 ]
211
+ function_arn = function_arn + f":{ function_qualifier } "
212
+ return function_arn
213
+
189
214
# e.g. arn:aws:apigateway:us-east-1::/restapis/xyz123/stages/default
190
215
if source .event_type == EventTypes .API_GATEWAY :
191
216
request_context = event .get ("requestContext" )
@@ -275,23 +300,35 @@ def extract_trigger_tags(event: dict, context: Any) -> dict:
275
300
if event_source_arn :
276
301
trigger_tags ["function_trigger.event_source_arn" ] = event_source_arn
277
302
278
- if event_source .event_type in [EventTypes .API_GATEWAY , EventTypes .ALB ]:
303
+ if event_source .event_type in [
304
+ EventTypes .API_GATEWAY ,
305
+ EventTypes .ALB ,
306
+ EventTypes .LAMBDA_FUNCTION_URL ,
307
+ ]:
279
308
trigger_tags .update (extract_http_tags (event ))
280
309
281
310
return trigger_tags
282
311
283
312
284
313
def extract_http_status_code_tag (trigger_tags , response ):
285
314
"""
286
- If the Lambda was triggered by API Gateway or ALB add the returned status code
315
+ If the Lambda was triggered by API Gateway, Lambda Function URL, or ALB add the returned status code
287
316
as a tag to the function execution span.
288
317
"""
289
- is_http_trigger = trigger_tags and (
290
- trigger_tags .get ("function_trigger.event_source" ) == "api-gateway"
291
- or trigger_tags .get ("function_trigger.event_source" )
292
- == "application-load-balancer"
293
- )
294
- if not is_http_trigger :
318
+ if trigger_tags is None :
319
+ return
320
+ str_event_source = trigger_tags .get ("function_trigger.event_source" )
321
+ # it would be cleaner if each event type was a constant object that
322
+ # knew some properties about itself like this.
323
+ str_http_triggers = [
324
+ et .value
325
+ for et in [
326
+ EventTypes .API_GATEWAY ,
327
+ EventTypes .LAMBDA_FUNCTION_URL ,
328
+ EventTypes .ALB ,
329
+ ]
330
+ ]
331
+ if str_event_source not in str_http_triggers :
295
332
return
296
333
297
334
status_code = "200"
0 commit comments