@@ -35,6 +35,7 @@ class EventTypes(_stringTypedEnum):
3535 CLOUDFRONT = "cloudfront"
3636 DYNAMODB = "dynamodb"
3737 KINESIS = "kinesis"
38+ LAMBDA_FUNCTION_URL = "lambda-function-url"
3839 S3 = "s3"
3940 SNS = "sns"
4041 SQS = "sqs"
@@ -115,6 +116,10 @@ def parse_event_source(event: dict) -> _EventSource:
115116
116117 request_context = event .get ("requestContext" )
117118 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 )
118123 event_source = _EventSource (EventTypes .API_GATEWAY )
119124 if "httpMethod" in event :
120125 event_source .subtype = EventSubtypes .API_GATEWAY
@@ -160,6 +165,14 @@ def parse_event_source(event: dict) -> _EventSource:
160165 return event_source
161166
162167
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+
163176def parse_event_source_arn (source : _EventSource , event : dict , context : Any ) -> str :
164177 """
165178 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
186199 aws_arn , account_id , distribution_id
187200 )
188201
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+
189214 # e.g. arn:aws:apigateway:us-east-1::/restapis/xyz123/stages/default
190215 if source .event_type == EventTypes .API_GATEWAY :
191216 request_context = event .get ("requestContext" )
@@ -275,23 +300,35 @@ def extract_trigger_tags(event: dict, context: Any) -> dict:
275300 if event_source_arn :
276301 trigger_tags ["function_trigger.event_source_arn" ] = event_source_arn
277302
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+ ]:
279308 trigger_tags .update (extract_http_tags (event ))
280309
281310 return trigger_tags
282311
283312
284313def extract_http_status_code_tag (trigger_tags , response ):
285314 """
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
287316 as a tag to the function execution span.
288317 """
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 :
295332 return
296333
297334 status_code = "200"
0 commit comments