Can I get information about AWS Lambda request IDs, e.g. the trigger? - aws-lambda

In my logs I find
START RequestId: 123a1a12-1234-1234-1234-123456789012 Version: $LATEST
for every invocation of AWS lambda. Is it possible to get more information about a request, e.g. what triggered it?

You can get the request id and other information from the context object.
When Lambda runs your function, it passes a context object to the handler. This object provides methods and properties that provide information about the invocation, function, and execution environment.
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html
You can get further information from the process.env variable.
I wrote a short lambda function (node.js) which logs these information to the console and ends up in aws cloud watch
exports.handler = async (event, context) => {
console.log('context:', JSON.stringify(context));
console.log('process.env:', JSON.stringify(process.env));
return {statusCode: 200, body: 'Hello World'};
};
Log output:
START RequestId: 6f3c103e-f0a5-4982-934c-dabedda0065e Version: $LATEST
context:
{
"callbackWaitsForEmptyEventLoop": true,
"functionVersion": "$LATEST",
"functionName": "my_lambda_function_name",
"memoryLimitInMB": "128",
"logGroupName": "/aws/lambda/my_lambda_function_name",
"logStreamName": "2020/10/01/[$LATEST]8adb13668eed4ac8b3e7f8d796fe4d49",
"invokedFunctionArn": "arn:aws:lambda:us-east-1:636121343751:function:my_lambda_function_name",
"awsRequestId": "6f3c103e-f0a5-4982-934c-dabedda0065e"
}
process.env:
{
"AWS_LAMBDA_FUNCTION_VERSION": "$LATEST",
"AWS_SESSION_TOKEN": "IZZ3eS6vFF...",
"LD_LIBRARY_PATH": "/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib",
"LAMBDA_TASK_ROOT": "/var/task",
"AWS_LAMBDA_LOG_GROUP_NAME": "/aws/lambda/my_lambda_function_name",
"AWS_LAMBDA_RUNTIME_API": "127.0.0.1:9001",
"AWS_LAMBDA_LOG_STREAM_NAME": "2020/10/01/[$LATEST]8adb13668eed4ac8b3e7f8d796fe4d49",
"AWS_EXECUTION_ENV": "AWS_Lambda_nodejs12.x",
"AWS_LAMBDA_FUNCTION_NAME": "my_lambda_function_name",
"AWS_XRAY_DAEMON_ADDRESS": "169.254.79.2:2000",
"PATH": "/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin",
"AWS_DEFAULT_REGION": "us-east-1",
"PWD": "/var/task",
"AWS_SECRET_ACCESS_KEY": "5nQrpKhBwF...",
"LAMBDA_RUNTIME_DIR": "/var/runtime",
"LANG": "en_US.UTF-8",
"NODE_PATH": "/opt/nodejs/node12/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules:/var/runtime:/var/task",
"AWS_REGION": "us-east-1",
"TZ": ":UTC",
"AWS_ACCESS_KEY_ID": "ASIAZNANWY3473BTADSB",
"SHLVL": "0",
"_AWS_XRAY_DAEMON_ADDRESS": "169.254.79.2",
"_AWS_XRAY_DAEMON_PORT": "2000",
"AWS_XRAY_CONTEXT_MISSING": "LOG_ERROR",
"_HANDLER": "index.handler",
"AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "128",
"_X_AMZN_TRACE_ID": "Root=1-6f75f4e5-5801599f17fd63e74ecd0833;Parent=73fb93812cdbf83f;Sampled=0"
}
END RequestId: 6f3c103e-f0a5-4982-934c-dabedda0065e
REPORT RequestId: 6f3c103e-f0a5-4982-934c-dabedda0065e
Duration: 21.71 ms Billed Duration: 100 ms
Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 132.35 ms

Not sure I understand what you mean by what triggered it? If it's connected to the API Gateway, then requests are proxied through the Gateway to your Lambda. In that case the Gateway triggered it, even though it was a proxied request.
Additionally and you can augment your Gateway to pass additional request info to your Lambda. See how
And also, to attach the request details to the RequestID you're seeing, you can check the context.awsRequestId.
I'd assume you want to do some form of log monitoring, in which case I think you can bundle up these request information(headers, query, params, body) and send to your log aggregator along with the awsRequestId.
Let me know if that helps
Further reference

A lambda function has two parameters: Event and context.
A normal invocation looks like this:
{
"event": {
"version": "0",
"id": "abcdefgh-1234-5678-1234-abcdefghijkl",
"detail-type": "Scheduled Event",
"source": "aws.events",
"account": "123456789012",
"time": "2018-01-01T12:00:00Z",
"region": "us-east-1",
"resources": [
"arn:aws:events:us-east-1:123456788901:rule/foo"
],
"detail": {}
},
"context": "<__main__.LambdaContext object at 0x123456ax1234>"
}
The test invocation has the elements you get.

You need to get this information from your lambda function context .
RequestId=context.aws_request_id
You will get following result
RequestId- "00cfaafe-5018-4be0-9668-b98daf5a7312" Version: $LATEST

Related

What comes with the AWS Lambda event and context

I've got AWS Lambda written in Ruby 2.7 and the Lambda is setup based on templates.yml. Since I'm not able to use debugger on AWS Lambda which is run locally (AWS SAM gives me an error: Ruby 2.7 is not supported at the moment - docs) I also can't check what's coming inside Event and Context.
My lambda uses the Gateway API, and I'm wondering what I should do to pull the entire payload (I assume it's in the body of the request) from the request that comes in at POST /quizzes, which looks like the following:
{
"quiz":
{
"first_name": "john",
"last_name": "doe",
"ssn": "1234",
"address":
{
"line1": "4444 NW ANYSTREET AVE",
"city": "anytown",
"state": "FL",
"zip_code": "33333"
},
"dob":
{
"day": 25,
"month": 12,
"year": 2000
}
}
}
From the entire Lambda Event I want to fetch and pass only the body that is attached to the request. In other words, what does the event look like with this type of request body?
If you want to know what an event in lambda looks like, you can use AWS SAM to generate the body of a fake event using the sam local generate-event command.

How to trigger lambda once Cloudformation stack is created

I have to trigger a lambda function once specific stack is created.
I have created the below CloudWatch event rule and associated the target to that lambda function but it is not triggering the lambda.
{
"source": [
"aws.cloudformation"
],
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"cloudformation.amazonaws.com"
],
"eventName": [
"CreateStack"
],
"stackName": [
"sql-automate-04-08"
]
}
}
Please let me know if i am missing anything here.
This doesn’t work using CloudWatch Event Rules because the CloudFormation stack’s lifecycle events don’t reflect individual API calls.
However, you can configure CloudFormation to send stack events to an Amazon SNS topic via its NotificationARNs property. An AWS Lambda function subscribed to that topic can then filter and process the events.
This EventBridge Rule has worked for me:
{
"source": ["aws.cloudformation"],
"detail-type": ["CloudFormation Stack Status Change"],
"region": ["us-east-1"],
"detail": {
"status-details": {
"status": ["CREATE_COMPLETE"]
}
}
}

CORS error with AWS api gateway and java lambda function

Today I created one api gateway on aws and one java lambda function. Then finally integrated api gateway with lambda function.
So when I hit the api using postman then it returns the result which is basically a list of customer. Till now everything looks fine. Following is the
#Override
public TestResponse handleRequest(Request input, Context context) {
TestService testService = SingletonServiceManager.getInstance().getTestService();
TestListResponse response = (TestListResponse)productListService.executeRequest(input);
return response;
}
After executing it returns following output.
{
"status": 200,
"products": [
{
"name": "test1",
"code": "test1",
"status": true
},
{
"name": "test2",
"code": "test2",
"status": true
}
]
}
but when I started integrating this with api call with Angular from local machine it start throwing CORS issue. Angular client using it CORS setting to connect.
Can someone help me on this. Do I need to enable something special from lambda function.
You need to enable CORS in your API Gateway configuration.

How to know which Lambda sent a message to the Dead Letter Queue?

I'm using a SNS Topic as a Dead Letter Queue to handle errors thrown by multiple Lambdas. In the error messages, there are the following attributes :
RequestID,
ErrorCode,
ErrorMessage,
However, I can't easily find which Lambda threw the error, since nothing related to it appear in the message (eg: ARN, function name...)
Although it's possible to look up the request ID on CloudWatch, or to create multiple topics, there should be a much easier way to find which Lambda threw the error. Below is the structure of the received message:
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "",
"Sns": {
"Type": "Notification",
"MessageId": "",
"TopicArn": "",
"Subject": null,
"Message": "",
"Timestamp": "",
"SignatureVersion": "",
"Signature": "",
"SigningCertUrl": "",
"UnsubscribeUrl": "",
"MessageAttributes": {
"RequestID": {
"Type": "String",
"Value": ""
},
"ErrorCode": {
"Type": "String",
"Value": "200"
},
"ErrorMessage": {
"Type": "String",
"Value": "test"
}
}
}
}
]
}
Is there any way to add information, such as the ARN, on the Lambda which triggered this error message?
You can use AWS CloudTrail to identify which Lambda executed:
https://docs.aws.amazon.com/lambda/latest/dg/logging-using-cloudtrail.html
You should have one DLQ per Lambda function. This will let you know where the dead letter is coming from.
I ended up configuring:
One unique SNS topic for every lambda DLQ.
A lambda listening to the above topic and storing the request ID in S3
A trail on CloudTrail logging every lambda invoke
A lambda matching the failed request ID in S3 and the cloudtrail logs. The latter provide the name of the failed lambda.
This infrastructure might seem a bit complicated but it's working very well. It allows to only add one unique onError: ... line of code in every lambda configuration file.
Not sure if you figured out a solution or not, but i solved a somewhat similar problem with a little help from boto3.
To give some more context about my setup:
I had 2 lambda functions (lambdaA and lambdaB) listening to a SNS topic which gets updated by S3 object creation events.
Both lambda functions use one SNS topic as DLQ which is subscribed by a single dlq lambda (lambdaDLQ).
In the lambdaDLQ's received message, you get a Message attribute which has the message received by the error throwing lambda functions (lambdaA or lambdaB) which contains the information about SNS message received by them.
So the steps i used to figure out the error throwing lambda function were:
Parse the Message attribute from lambdaDLQ's event into json.
Get the EventSubscriptionArn from the above parsed message. This holds the subscription details of the error throwing lambda.
Using boto3 to get Protocol, Endpoint, etc. Which give the name of the error throwing lambda.
sns_client = boto3.client('sns')
arn = 'arn_goes_here'
response = sns_client.get_subscription_attributes(SubscriptionArn=arn)
In case your error throwing lambda functions do not listen to a SNS topic, you might need to change this a little bit.

How do I post a test Kinesis event from Postman to a local Lambda function running on serverless?

Sorry, wasn't sure how to make the question itself brief enough...
I can post data from Postman to my local Lambda function. The issue is that when running locally, I have use this line of code...
event = JSON.parse(event.body);
...so that I can do this...
event.Records.forEach(function(record)
{
// do some stuff
}
But when I deploy the function to AWS, parsing event.body is unnecessary. In fact it throws an error.
I was assuming that there is something different about the JSON (or other aspects of the request) that I'm posting from Postman to my local app when compared to what Kinesis actually sends. But the JSON blob I'm posting locally was logged directly from Lambda on AWS to Cloudwatch.
I'm missing something.
TBH, this only matters because having to comment out that line as a step in the deployment process is annoying and error-prone.
Here's the JSON (names have been changed to protect the innocent):
{
"Records": [
{
"kinesis": {
"kinesisSchemaVersion": "1.0",
"partitionKey": "Thursday, 11 April 2019",
"sequenceNumber": "49594660145138471912435706107712688932829223550684495922",
"data": "some base 64 stuff",
"approximateArrivalTimestamp": 1555045874.83
},
"eventSource": "aws:kinesis",
"eventVersion": "1.0",
"eventID": "shardId-000000000003:1234123412341234123412341234123412341234123412341234",
"eventName": "aws:kinesis:record",
"invokeIdentityArn": "arn:aws:iam::1234123412341234:role/lambda-kinesis-role",
"awsRegion": "us-west-2",
"eventSourceARN": "arn:aws:kinesis:us-west-2:1234123412341234:stream/front-end-requests"
}
]
}

Resources