Skip to content

Commit dbafab0

Browse files
authored
Merge pull request #2793 from BigBoss531/BigBoss531-feature-apigw-lambda-sns-enhanced-monitoring
Enhance apigw-lambda-sns pattern with production-ready improvements
2 parents 584ecdd + 6711c83 commit dbafab0

File tree

6 files changed

+274
-34
lines changed

6 files changed

+274
-34
lines changed

apigw-lambda-sns/Readme.md renamed to apigw-lambda-sns/README.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,22 @@
22

33
The SAM template deploys a API Gateway REST API with Lambda function integration, an SNS topic and the IAM permissions required to run the application. Whenever the REST API is invoked, the Lambda function publishes a message to the SNS topic. The AWS SAM template deploys the resources and the IAM permissions required to run the application.
44

5+
## Features
6+
7+
- **API Gateway REST API** with Lambda integration
8+
- **Lambda function** that publishes messages to SNS
9+
- **SNS topic** for message publishing
10+
- **CloudWatch Alarm** monitoring API errors
11+
- **Amazon CloudWatch Synthetics Canary** for automated API endpoint monitoring
12+
- **AWS X-Ray tracing** enabled for distributed tracing on LAmbda and APIGW (incurs additional costs)
13+
- **S3 bucket** for Synthetics artifacts storage
14+
515
Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/apigw-lambda-sns/.
616

7-
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
17+
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. **Note: AWS X-Ray tracing is enabled which incurs additional charges based on traces recorded and retrieved.** You are responsible for any AWS costs incurred. No warranty is implied in this example.
818

919
## Requirements
1020

11-
1221
* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
1322
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
1423
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
@@ -50,19 +59,27 @@ curl --location --request GET 'https://<api_id>.execute-api.<region>.amazonaws.c
5059
```
5160
In order to receive a notification, please make sure to configure subscription in the SNS topic.
5261
62+
### Additional Features
5363
54-
## Cleanup
64+
- **CloudWatch Alarm**: Monitor the Synthetics Canary failures. The alarm triggers when the canary fails at least once within a 5-minute period.
65+
- **Synthetics Canary**: Automatically tests the API endpoint every minute to ensure availability. If you want to alarm on this, you must manually create a CloudWatch Alarm or update the template
66+
- **X-Ray Tracing**: Distributed tracing is enabled for both API Gateway and Lambda to help with debugging and performance analysis.
5567
5668
69+
## Cleanup
70+
5771
1. Delete the stack
5872
```
5973
aws cloudformation delete-stack —stack-name STACK_NAME
6074
```
61-
2. Confirm the stack has been deleted
75+
2. **Manually delete the S3 bucket** - The Synthetics artifacts bucket must be manually emptied and deleted after stack deletion
76+
3. Confirm the stack has been deleted
6277
```
6378
aws cloudformation list-stacks —query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"
6479
```
6580
81+
**Important**: You must manually delete the S3 bucket created for Synthetics artifacts after deleting the CloudFormation stack, as it will contain canary run artifacts.
82+
6683
----
6784
Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6885

apigw-lambda-sns/api.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,23 @@ paths:
1717
application/json:
1818
schema:
1919
$ref: "#/components/schemas/Empty"
20+
"400":
21+
description: "400 response"
22+
"500":
23+
description: "500 response"
2024
x-amazon-apigateway-integration:
2125
httpMethod: "POST"
2226
uri: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaFunctionName/invocations"
2327
responses:
2428
default:
2529
statusCode: "200"
30+
".*4\\d{2}.*":
31+
statusCode: "400"
32+
".*5\\d{2}.*":
33+
statusCode: "500"
2634
passthroughBehavior: "when_no_match"
2735
contentHandling: "CONVERT_TO_TEXT"
28-
type: "aws"
36+
type: "aws_proxy"
2937
components:
3038
schemas:
3139
Empty:
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"title": "Amazon API Gateway REST API to Lambda to SNS",
3+
"description": "Integration of Amazon API Gateway REST API with Amazon Lambda to publish to Amazon SNS with enhanced monitoring",
4+
"language": "Python",
5+
"level": "200",
6+
"framework": "AWS SAM",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"This sample project demonstrates how to publish to a SNS Topic whenever the REST API is invoked using Lambda function.",
11+
"This pattern deploys a Amazon API Gateway REST API with Lambda Function integration and SNS Topic with enhanced monitoring features including CloudWatch Alarms, X-Ray tracing, and Synthetics Canary."
12+
]
13+
},
14+
"gitHub": {
15+
"template": {
16+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-lambda-sns",
17+
"templateURL": "serverless-patterns/apigw-lambda-sns",
18+
"projectFolder": "apigw-lambda-sns",
19+
"templateFile": "template.yaml"
20+
}
21+
},
22+
"resources": {
23+
"bullets": [
24+
{
25+
"text": "Choosing between messaging services for serverless applications.",
26+
"link": "https://aws.amazon.com/blogs/compute/choosing-between-messaging-services-for-serverless-applications/"
27+
},
28+
{
29+
"text": "Publishing Messages in Amazon SNS",
30+
"link": "https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns.html#topic"
31+
},
32+
{
33+
"text": "AWS X-Ray Distributed Tracing",
34+
"link": "https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html"
35+
},
36+
{
37+
"text": "Amazon CloudWatch Synthetics",
38+
"link": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries.html"
39+
}
40+
]
41+
},
42+
"deploy": {
43+
"text": [
44+
"sam deploy"
45+
]
46+
},
47+
"testing": {
48+
"text": [
49+
"See the GitHub repo for detailed testing instructions."
50+
]
51+
},
52+
"cleanup": {
53+
"text": [
54+
"Delete the stack: <code>sam delete</code>.",
55+
"Manually delete the S3 bucket created for Synthetics artifacts after deleting the CloudFormation stack."
56+
]
57+
},
58+
"authors": [
59+
{
60+
"name": "Sanskar",
61+
"image": "https://drive.google.com/file/d/1dP8XHHevaOC-eEKOq6Gty75ZBZ428KHT/view?usp=sharing",
62+
"bio": "Sanskar is a Serverless Cloud Engineer at Amazon Web Services and is based in India. Sanskar has avid interest in microservices and serverless patterns.",
63+
"linkedin": "sanskar05"
64+
}
65+
]
66+
}

apigw-lambda-sns/example-pattern.json

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"title": "Amazon API Gateway REST API to Lambda to SNS",
3-
"description": "Integration of Amazon API Gateway REST API with Amazon Lambda to publish to Amazon SNS",
3+
"description": "Integration of Amazon API Gateway REST API with Amazon Lambda to publish to Amazon SNS with enhanced monitoring",
44
"language": "Python",
55
"level": "200",
66
"framework": "AWS SAM",
77
"introBox": {
88
"headline": "How it works",
99
"text": [
1010
"This sample project demonstrates how to publish to a SNS Topic whenever the REST API is invoked using Lambda function.",
11-
"This pattern deploys a Amazon API Gateway REST API with Lambda Function integration and SNS Topic."
11+
"This pattern deploys a Amazon API Gateway REST API with Lambda Function integration and SNS Topic with enhanced monitoring features including CloudWatch Alarms, X-Ray tracing, and Synthetics Canary."
1212
]
1313
},
1414
"gitHub": {
@@ -29,6 +29,14 @@
2929
"text": "Publishing Messages in Amazon SNS",
3030
"link": "https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns.html#topic"
3131
},
32+
{
33+
"text": "AWS X-Ray Distributed Tracing",
34+
"link": "https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html"
35+
},
36+
{
37+
"text": "Amazon CloudWatch Synthetics",
38+
"link": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries.html"
39+
},
3240
]
3341
},
3442
"deploy": {
@@ -43,7 +51,8 @@
4351
},
4452
"cleanup": {
4553
"text": [
46-
"Delete the stack: <code>same delete</code>."
54+
"Delete the stack: <code>sam delete</code>.",
55+
"Manually delete the S3 bucket created for Synthetics artifacts after deleting the CloudFormation stack."
4756
]
4857
},
4958
"authors": [

apigw-lambda-sns/src/code.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,38 @@ def lambda_handler(event, context):
1111
logger.setLevel(logging.INFO)
1212
logger.info("request: " + json.dumps(event))
1313

14-
topic_arn = os.environ.get('TOPIC_ARN')
15-
16-
sns_client = boto3.client("sns")
17-
1814
try:
15+
topic_arn = os.environ.get('TOPIC_ARN')
16+
if not topic_arn:
17+
logger.error("Missing TOPIC_ARN environment variable")
18+
return {
19+
"statusCode": 500,
20+
"body": json.dumps({"error": "Server configuration error"})
21+
}
22+
23+
sns_client = boto3.client("sns")
1924
sent_message = sns_client.publish(
2025
TargetArn=topic_arn,
2126
Message=json.dumps({'default': json.dumps(event)})
2227
)
2328

24-
if sent_message is not None:
25-
logger.info(f"Success - Message ID: {sent_message['MessageId']}")
29+
logger.info(f"Success - Message ID: {sent_message['MessageId']}")
2630
return {
2731
"statusCode": 200,
28-
"body": json.dumps("Success")
32+
"body": json.dumps({"status": "Success", "messageId": sent_message['MessageId']})
2933
}
3034

3135
except ClientError as e:
32-
logger.error(e)
33-
return None
36+
error_code = e.response['Error']['Code']
37+
error_message = e.response['Error']['Message']
38+
logger.error(f"ClientError: {error_code} - {error_message}")
39+
return {
40+
"statusCode": 500,
41+
"body": json.dumps({"error": "Failed to publish message to SNS"})
42+
}
43+
except Exception as e:
44+
logger.error(f"Unexpected error: {str(e)}")
45+
return {
46+
"statusCode": 500,
47+
"body": json.dumps({"error": "Internal server error"})
48+
}

0 commit comments

Comments
 (0)