Hello cloud fans! In this next step of our resume challenge, we're going to keep track of how many people visit our blog using AWS. We will use a Lambda function to save these numbers into a DynamoDB database and connect everything with an API Gateway endpoint. If you missed the earlier part, make sure to read it first. Let's get started!
Step 1: Creating the DynamoDB Table
So, we will create a table to store the visitor count. Just head to your console, type DynamoDB in the search bar, and follow these steps.
Start by choosing a name for your table. Be careful with this name because it will be used in the Lambda code in the next step.
And do the same for the partition key. You can leave the Sort key empty.
Choose Customize settings
and select On-demand
pricing (to stay within the free tier).
You can leave the rest as default and create the table.
Step 2: Create Lambda Function
We will create a backend Lambda function using Python. Head to your console, type "Lambda" in the search bar, and create your Lambda function with Python 3.12 (or another language). For a step-by-step tutorial, visit this link.
Copy and paste the provided code into the designated area, then be sure to click 'Deploy' to activate it. Remember to replace TableName
and partition_key
with the specific names you have selected earlier.
import json
import boto3
from botocore.exceptions import ClientError
# Initialize the DynamoDB client
client = boto3.client('dynamodb')
# Access environment variables
TableName = "Visitors"
partition_key = "stat"
def lambda_handler(event, context):
try:
current_view_response = client.get_item(
TableName=TableName,
Key={partition_key: {'S': 'view-count'}}
)
if 'Item' in current_view_response and 'Quantity' in current_view_response['Item']:
current_view_count = int(current_view_response['Item']['Quantity']['N'])
else:
current_view_count = 0 # Initialize if not present
except ClientError as error:
print(error)
raise
# If the Quantity was not set, increment the page view count
if current_view_count == 0:
newCount = current_view_count + 1
try:
client.update_item(
TableName=TableName,
Key={'stat': {'S': 'view-count'}},
UpdateExpression='SET Quantity = :val',
ExpressionAttributeValues={':val': {'N': str(newCount)}},
ReturnValues='UPDATED_NEW'
)
except ClientError as error:
print(error)
raise
else:
# If the Quantity is set, use the existing count
newCount = current_view_count
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST,GET',
},
'body': json.dumps({'count': newCount})
}
Attempting to test the code at this stage will result in an error message.
{
"errorMessage": "An error occurred (AccessDeniedException) when calling the GetItem operation: User: arn:aws:sts::<account_number>:assumed-role/visitor-role-xxxxxx/visitor is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:us-east-1:<account_number>:table/Visitors because no identity-based policy allows the dynamodb:GetItem action",
"errorType": "ClientError",
"requestId": "7c819f77-21c6-45fb-9248-0a0dd5f0a0ca",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 13, in lambda_handler\n current_view_response = client.get_item(\n",
" File \"/var/lang/lib/python3.12/site-packages/botocore/client.py\", line 553, in _api_call\n return self._make_api_call(operation_name, kwargs)\n",
" File \"/var/lang/lib/python3.12/site-packages/botocore/client.py\", line 1009, in _make_api_call\n raise error_class(parsed_response, operation_name)\n"
]
}
This is an indicator that your Lambda function lacks the necessary permissions to interact with the earlier created DynamoDB table. Let's address this by updating the function's permissions.
Let's resolve this by adding an inline policy to grant Lambda the permissions it requires.
Next, paste the policy into the appropriate section, and remember to substitute the account_id
, region
and TableName
placeholders with your actual account details for a seamless setup.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:UpdateItem",
"dynamodb:PutItem",
"dynamodb:Scan",
"dynamodb:DeleteItem"
],
"Resource": [
"arn:aws:dynamodb:<region>:<account_id>:table/<TableName>"
]
}
]
}
Once you've entered the policy details, simply assign a name to your policy and click the 'Create policy' button to finalize the process.
Now that you've set the permissions, it's time to test it out. Cross your fingers, press that button, and with a little bit of tech magic, it should work like a charm!
Step 3: Add an API Gateway trigger
Adding a trigger to your Lambda function is straightforward—just a simple button click away. Navigate to your Lambda function's configuration and effortlessly add the trigger.
Choose API Gateway
Next, you'll need to choose between REST API and HTTP API. To make an informed decision, I suggest perusing the accompanying documentation.
Leave the remaining settings at their default values and then click 'Add' to proceed.
To test if you've done it well, click on the link an refrech the page and see if the count increases.
Conclusion
By following these steps, you've set up a system to track and store your portfolio traffic using AWS services. This enhances your resume and provides insights into your website's performance. Keep experimenting and expanding your cloud skills!
Created a DynamoDB table to store visitor counts.
Developed a backend Lambda function using Python to interact with the DynamoDB table.
Configured necessary IAM permissions for the Lambda function.
Added an API Gateway trigger to the Lambda function.
Tested the setup to ensure it tracks and stores portfolio traffic successfully.
I have created a GitHub repository to automate the process using Terraform. Enjoy your traffic and stay tuned for the next part, where we will link our front-end code with the endpoint we created today.