in elasticapm/contrib/serverless/aws.py [0:0]
def __enter__(self):
"""
Transaction setup
"""
if not isinstance(self.event, dict):
# When `event` is not a dict, it's likely the output of another AWS
# service like Step Functions, and is unlikely to be standardized
# in any way. We just have to rely on our defaults in this case.
self.event = {}
headers = self.event.get("headers") or {}
if headers and should_normalize_headers(self.event):
normalized_headers = {k.lower(): v for k, v in headers.items()}
else:
normalized_headers = headers
trace_parent = TraceParent.from_headers(normalized_headers)
global COLD_START
cold_start = COLD_START
COLD_START = False
self.source = "other"
transaction_type = "request"
transaction_name = os.environ.get("AWS_LAMBDA_FUNCTION_NAME", self.name)
self.httpmethod = (
nested_key(self.event, "requestContext", "httpMethod")
or nested_key(self.event, "requestContext", "http", "method")
or nested_key(self.event, "httpMethod")
)
if self.httpmethod: # http request
if nested_key(self.event, "requestContext", "elb"):
self.source = "elb"
resource = "unknown route"
elif nested_key(self.event, "requestContext", "httpMethod"):
self.source = "api"
# API v1
resource = "/{}{}".format(
nested_key(self.event, "requestContext", "stage"),
nested_key(self.event, "requestContext", "resourcePath"),
)
else:
self.source = "api"
# API v2
route_key = nested_key(self.event, "requestContext", "routeKey")
route_key = f"/{route_key}" if route_key.startswith("$") else route_key.split(" ", 1)[-1]
resource = "/{}{}".format(
nested_key(self.event, "requestContext", "stage"),
route_key,
)
transaction_name = "{} {}".format(self.httpmethod, resource)
elif "Records" in self.event and len(self.event["Records"]) == 1:
record = self.event["Records"][0]
if record.get("eventSource") == "aws:s3": # S3
self.source = "s3"
transaction_name = "{} {}".format(record["eventName"], record["s3"]["bucket"]["name"])
elif record.get("EventSource") == "aws:sns": # SNS
self.source = "sns"
transaction_type = "messaging"
transaction_name = "RECEIVE {}".format(record["Sns"]["TopicArn"].split(":")[5])
elif record.get("eventSource") == "aws:sqs": # SQS
self.source = "sqs"
transaction_type = "messaging"
transaction_name = "RECEIVE {}".format(record["eventSourceARN"].split(":")[5])
if "Records" in self.event:
links = [
TraceParent.from_string(record["messageAttributes"]["traceparent"]["stringValue"])
for record in self.event["Records"][:1000]
if "messageAttributes" in record and "traceparent" in record["messageAttributes"]
]
else:
links = []
self.client.begin_transaction(transaction_type, trace_parent=trace_parent, links=links)
elasticapm.set_transaction_name(transaction_name, override=False)
if self.source in SERVERLESS_HTTP_REQUEST:
elasticapm.set_context(
lambda: get_data_from_request(
self.event,
capture_body=self.client.config.capture_body in ("transactions", "all"),
capture_headers=self.client.config.capture_headers,
),
"request",
)
self.set_metadata_and_context(cold_start)
self.send_partial_transaction()
return self