47

As explained in the Docs , I set up Lambda@edge for cloudfront trigger of Viewer Response.

The lambda function code :

'use strict';

exports.handler = (event, context, callback) => {
    console.log('----EXECUTED------');

    const response = event.Records[0].cf.response;      
    console.log(event.Records[0].cf_response);

    callback(null, response);
};

I have set up trigger appropriately for the Viewer Response event.

Now when I make a request through cloudfront, it must be logged in cloudwatch, but it doesn't.
If I do a simple Test Lambda Function (using Button), it is logged properly.

What might be the issue here ?

Yves M.
  • 29,855
  • 23
  • 108
  • 144
formatkaka
  • 1,278
  • 3
  • 13
  • 27
  • 7
    You should find that it's being logged in the AWS region where the CloudFront edge location you're currently hitting is located, which should be a region near where you are located. Testing always logs to us-east-1 but not real traffic. You could also add `response.headers['x-lambda-region'] = [ { key: 'X-Lambda-Region', value: process.env.AWS_REGION } ];` to your code (before the callback) and if your trigger is running successfully, you'll see that an `X-Lambda-Region` header has been added to the response, telling you which region was involved in processing your request. Your thoughts? – Michael - sqlbot Sep 30 '17 at 17:28

5 Answers5

76

When you deploy Lambda@Edge function, It is deployed to all edge cache regions across the world with their version Replica of the Lambda Edge function. Regional edge caches are a subset of the main AWS regions and edge locations.

When a user requests to the nearest pop/edge, the lambda associated with the edge cache region will get called. All logs of Lambda associated with those regions will in their edge cache region CloudWatch logs.

For example:

If a user is hitting us-east-1 region then its associated logs will be in us-east-1.

To know exactly where (on which region) your function is logging, you can run this AWS CLI script:

FUNCTION_NAME=function_name_without_qualifiers
for region in $(aws --output text  ec2 describe-regions | cut -f 3) 
do
    for loggroup in $(aws --output text  logs describe-log-groups --log-group-name "/aws/lambda/us-east-1.$FUNCTION_NAME" --region $region --query 'logGroups[].logGroupName')
    do
        echo $region $loggroup
    done
done

on which you have to replace "function_name_without_qualifiers" with the name of your lambda@edge. Link

Hope it helps.

diffa
  • 2,986
  • 1
  • 22
  • 35
Kannaiyan
  • 12,554
  • 3
  • 44
  • 83
  • 1
    Thanks... actually while configuring cloudfront I set `Price Class Use Only US, Canada and Europe` , my nearest Edge is `Asia Pacific (Mumbai)` but it was actually hitting on `EU (Frankfurt)`. Thanks – formatkaka Oct 01 '17 at 01:43
  • 7
    Wow, spent half a day looking for those logs... only to find this SO post as a first Google search result. THANK YOU! – Paweł Gościcki Apr 06 '18 at 10:08
  • 2
    just wasted a day on this. Thank you!!! Another important gotya is that you can only define lambda@edge functions in the us-east-1 region, but they can then be triggered on any cloudfront distro. – Berty Jan 18 '19 at 13:35
  • 8
    I made 2 edits to get this to work today. One is to change `cut -3` to `cut -4` and the other is remove the hardcoded us-east-1 from the log group name. It wasn't part of the log group name for me. All that being done, I'm still not getting any logs. I see logs for my test runs, but CloudFront isn't doing anything. – jiggy Aug 11 '20 at 20:55
  • @jiggy check your lambda's role permissions. In my case, looks like by default it had granted permission to write logs only for 1 region. – Scofield Aug 24 '22 at 08:53
  • This had me crazy for hours, and when I finally found this post and went OMG, I struggled some more assuming my location in the south of Sweden would hit Stockholm, 500 km away, but Frankfurt at 700 km away was apparently preferred. AWS could really have improved the experience when debugging edge lambdas. – JHH Mar 24 '23 at 13:49
32

For those who have also searched for logs and couldn't find them with the script provided by @Kannaiyan.

TL;DR

Use this IAM Role for your Lambda function

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": "logs:CreateLogGroup",
        "Resource": "arn:aws:logs:*:*:*"
    },
    {
        "Effect": "Allow",
        "Action": [
            "logs:CreateLogStream",
            "logs:PutLogEvents"
        ],
        "Resource": [
            "arn:aws:logs:*:*:log-group:*:*"
        ]
    }
  ]
}

====

Make sure you have correct IAM role. If you created a Lambda first and then deployed it to Lambda@Edge, automatically generated IAM Role will only have permissions enough to log data in a single region into the log group named after the Lambda function, whilst using Lambda@Edge means it'll try to log data in different regions into the "/aws/lambda/." log group. Therefore it is necessary to change the IAM Role to allow creation of log group and write access there in different regions. In the TL;DR section, I provided the sample IAM Role, but make sure to narrow down the access to the specific list of log groups in production

  • 2
    If your role assumes the AWSLambdaBasicExecutionRole, you should get those permissions. – Doug Jan 27 '21 at 14:58
  • 1
    This was the reason for me. Had created a lambda function first (using the console), and then added it to cloudfront as lambda@edge, so it had us-east-1 as the region, so no log-groups were getting created in the edge location. – Rajeev Mar 17 '22 at 14:08
  • Same as Rajeev for me – Russell Keane Jul 12 '22 at 16:14
10

According to AWS Documentation for Lambda@Edge Functions:

When you check for the log files, be aware that log files are stored in the Region closest to the location where the function is executed. So if you visit a website from, for example, London, you must change the Region to view the CloudWatch Logs for the London Region.

captainblack
  • 4,107
  • 5
  • 50
  • 60
5

The Lambda@Edge logs and what region a request was executed in are available in the AWS CloudFront console, although the path is convoluted and AWS did a really lousy job of documenting the steps.

Here are the steps that work as of this posting:

  1. Navigate to the AWS CloudFront console.
  2. Click the "Monitoring" link under the "Telemetry" section (not "Logs", that takes to you CloudFront logs).
  3. Click on the "Lambda@Edge" tab.
  4. Choose your Lambda function and then click the "View metrics" button.

You can then use the "Invocations" graph to determine in which region a specific invocation of the Lambda function was executed. Once you have the region, you can, at long last, use the "View function logs" drop-down menu to view the Lambda function's logs for a specific region.

I figured this out by digging around in the console for a long time. The "documentation" for this logging is here, but doesn't seem to explain how to actually find Lambda@Edge logs for a specific region.

If anyone happens to find proper documentation about this, please update the post.

Nick A. Watts
  • 819
  • 10
  • 16
2

Following on from @yevhenii-hordashnyk's answer, if you're using "Serverless" framework, by default it creates a IAM user with logging permissions for the execution region only, and it is locked to the application name (which does not work for Edge functions because they are prefixed by the region of the installed function, thus requiring different permissions).

You have to specify a custom role, and apply that role to your function as per https://www.serverless.com/framework/docs/providers/aws/guide/iam

Note the following snippet uses * instead of - Ref: 'AWS::Region', as well as additional edgelambda.amazonaws.com service in Trust Relationships.

        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
                  - edgelambda.amazonaws.com
              Action: sts:AssumeRole

        Policies:
          - PolicyName: myPolicyName
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow # note that these rights are given in the default policy and are required if you want logs out of your lambda(s)
                  Action:
                    - logs:CreateLogGroup
                    - logs:CreateLogStream
                    - logs:PutLogEvents
                  Resource:
                    - 'Fn::Join':
                      - ':'
                      -
                        - 'arn:aws:logs'
                        - '*'
                        - Ref: 'AWS::AccountId'
                        - 'log-group:/aws/lambda/*:*:*'

By default it does add the `AWSLambdaVPCAccessExecutionRole` policy to the lambda role, but I do not know why it does not create the Log Stream. Maybe I've missed something, but after doing the above, it works now.
Daryl Teo
  • 5,394
  • 1
  • 31
  • 37