Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit 4abaa53

Browse files
committed
Merge branch 'develop'
2 parents 5eaed73 + 397301e commit 4abaa53

9 files changed

+173
-20
lines changed

CHANGELOG.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# terraform-aws-sns-to-cloudwatch-logs-lambda Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6+
7+
## [1.0.0] - 2019-03-30
8+
9+
- Moved all Python dependancies to Lambda Layers
10+
- Python function editable in repository and in Lambda UI
11+
- Default Python version switched to 3.6
12+
- Add optional dynamically calculated function name based on topic and Cloudwatch Group/Stream
13+
- Optionally create custom Lambda Layer zip using [build-lambda-layer-python submodule](https://github.com/robertpeteuil/build-lambda-layer-python)
14+
- Enables adding/changing dependancies
15+
- Enables compiling for different version of Python
16+
- Add new variable `lambda_runtime`
17+
18+
## [0.2.6] - 2018-10-14
19+
20+
Add ability to assign tags to created lambda function using new map variable `lambda_tags`
21+
22+
## [0.2.5] - 2018-10-09
23+
24+
Comment Cleanup
25+
26+
## [0.2.4] - 2018-08-20
27+
28+
Update README
29+
30+
## [0.2.3] - 2018-08-01
31+
32+
Update README
33+
34+
## [0.2.2] - 2018-08-01
35+
36+
Update README
37+
38+
## [0.2.1] - 2018-07-29
39+
40+
Added additional outputs:
41+
42+
- `lambda_version` - Latest published version of Lambda Function
43+
- `lambda_last_modified` - The date the Lambda Function was last modified
44+
45+
## [0.2.0] - 2018-07-28
46+
47+
Update README
48+
49+
## [0.1.3] - 2018-07-28
50+
51+
Add additional outputs
52+
53+
## [0.1.2] - 2018-07-28
54+
55+
Minor Edits
56+
57+
## [0.1.1] - 2018-07-28
58+
59+
Adjust outputs
60+
61+
## [0.1.0] - 2018-07-28
62+
63+
Initial Release
64+
65+
[1.0.0]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.6...1.0.0
66+
[0.2.6]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.5...0.2.6
67+
[0.2.5]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.4...0.2.5
68+
[0.2.4]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.3...0.2.4
69+
[0.2.3]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.2...0.2.3
70+
[0.2.2]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.1...0.2.2
71+
[0.2.1]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.2.0...0.2.1
72+
[0.2.0]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.1.3...0.2.0
73+
[0.1.3]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.1.2...0.1.3
74+
[0.1.2]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.1.1...0.1.2
75+
[0.1.1]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/compare/0.1.0...0.1.1
76+
[0.1.0]: https://github.com/robertpeteuil/terraform-aws-sns-to-cloudwatch-logs-lambda/tree/0.1.0

README.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,34 @@
88

99
This Module allows simple and rapid deployment
1010

11-
- Creates Lambda function, IAM Policies, Triggers, and Subscriptions
11+
- Creates Lambda function, Lambda Layer, IAM Policies, Triggers, and Subscriptions
1212
- Creates (or use existing) SNS Topic, CloudWatch Log Group and Log Group Stream
1313
- Options:
1414
- Create CloudWatch Event to prevent Function hibernation
1515
- Set Log Group retention period
16+
- Python function editable in repository and in Lambda UI
17+
- Python dependancies packages in Lambda Layers zip
18+
- Optionally create custom Lambda Layer zip using [build-lambda-layer-python](https://github.com/robertpeteuil/build-lambda-layer-python)
19+
- Enables adding/changing dependancies
20+
- Enables compiling for different version of Python
1621

1722
## SNS to CloudWatch Logs Features
1823

1924
This Lambda Function forwards subject & body of SNS messages to CloudWatch Log Group Stream
2025

21-
- Enhances the value of CloudWatch Logs by enabling on-demand entry creation from any service, function and script
26+
- Enhances the value of CloudWatch Logs by enabling easy entry creation from any service, function and script that can send SNS notifications
2227
- Enables cloud-init, bootstraps and functions to easily write log entries to a centralized CloudWatch Log
2328
- Simplifies troubleshooting of solutions with decentralized logic
2429
- scripts and functions spread across instances, Lambda and services
2530
- Easily add instrumentation to scripts: `aws sns publish --topic-arn $TOPIC_ARN --message $LOG_ENTRY`
26-
- Use with IAM instance policy may require `--region $AWS_REGION` parameter
31+
- Use with IAM instance policy requires `--region $AWS_REGION` parameter
2732

2833
## Usage
2934

3035
``` ruby
3136
module "sns_logger" {
3237
source = "robertpeteuil/sns-to-cloudwatch-logs-lambda/aws"
33-
version = "0.2.6"
38+
version = "1.0.0"
3439

3540
aws_region = "us-west-2"
3641
sns_topic_name = "projectx-logging"
@@ -58,10 +63,11 @@ module "sns_logger" {
5863
| create_log_group | Create new log group | string | `true` | no |
5964
| create_log_stream | Create new log stream | string | `true` | no |
6065
| log_group_retention_days | Log Group retention (days) | string | `0` (forever) | no |
61-
| lambda_func_name | Name for Lambda Function | string | `SNStoCloudWatchLogs` | no |
66+
| lambda_func_name | Name for Lambda Function | string | dynamically calculated | no |
6267
| lambda_description | Lambda Function Description | string | `Route SNS messages to CloudWatch Logs` | no |
6368
| lambda_tags | Mapping of Tags to assign to Lambda function | map | `{}` | no |
6469
| lambda_publish_func | Publish Lambda Function | string | `false` | no |
70+
| lambda_runtime | Lambda runtime for Function | string | `python3.6` | no |
6571
| lambda_timeout | Function time-out (seconds) | string | `3` | no |
6672
| lambda_mem_size | Function RAM assigned (MB) | string | `128` | no |
6773
| create_warmer_event | Create CloudWatch trigger event to prevent hibernation | string | `false` | no |

base_python3.6.zip

5.71 MB
Binary file not shown.

function/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
watchtower

function/sns_cloudwatch_gw.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Write log entries to cloudwatch logs."""
2+
3+
from __future__ import print_function
4+
import logging
5+
import watchtower
6+
import os
7+
8+
log_group = os.getenv('log_group')
9+
log_stream = os.getenv('log_stream')
10+
logger = logging.getLogger(__name__)
11+
logger.setLevel(logging.INFO)
12+
aws_handler = watchtower.CloudWatchLogHandler(log_group=log_group, stream_name=log_stream)
13+
logger.addHandler(aws_handler)
14+
15+
16+
def main(event, context):
17+
18+
try:
19+
message_source = event['Records'][0]['EventSource']
20+
except KeyError:
21+
return
22+
23+
if message_source == 'aws:sns':
24+
subject = event['Records'][0]['Sns']['Subject']
25+
body = event['Records'][0]['Sns']['Message']
26+
27+
if subject:
28+
logger.info("{}\n{}".format(subject, body))
29+
else:
30+
logger.info(body)
31+
32+
aws_handler.flush()
33+
34+
return 'Generated by Lambda'

main.tf

+42-12
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,54 @@ terraform {
66
required_version = "~> 0.11.7"
77
}
88

9+
provider "aws" {
10+
region = "${var.aws_region}"
11+
}
12+
13+
# -----------------------------------------------------------------
14+
# CREATE LAMBDA BASE LAYER CONTAINING PYTHON LIBRARIES
15+
# -----------------------------------------------------------------
16+
17+
resource "aws_lambda_layer_version" "logging_base" {
18+
filename = "${path.module}/base_${var.lambda_runtime}.zip"
19+
source_code_hash = "${base64sha256(file("${path.module}/base_${var.lambda_runtime}.zip"))}"
20+
21+
layer_name = "sns-cloudwatch-base-${replace(var.lambda_runtime,".","")}"
22+
description = "python logging and watchtower libraries"
23+
24+
compatible_runtimes = ["${var.lambda_runtime}"]
25+
}
26+
927
# -----------------------------------------------------------------
10-
# CREATE LAMBDA FUNCTION - SNS TO CLOUDWATCH LOGS GATEWAY
11-
# environment variables used for the 'log_group' and 'log_stream'
12-
# function published if 'lambda_publish_func' set
28+
# CREATE LAMBDA FUNCTION USING ZIP FILE
1329
# -----------------------------------------------------------------
1430

31+
# make zip
32+
data "archive_file" "lambda_function" {
33+
type = "zip"
34+
source_file = "${path.module}/function/sns_cloudwatch_gw.py"
35+
output_path = "${path.module}/lambda.zip"
36+
}
37+
38+
locals {
39+
dynamic_description = "Routes SNS topic '${var.sns_topic_name}' to CloudWatch group '${var.log_group_name}' and stream '${var.log_stream_name}'"
40+
}
41+
42+
# create lambda using function only zip on top of base layer
1543
resource "aws_lambda_function" "sns_cloudwatchlog" {
16-
function_name = "${var.lambda_func_name}"
17-
description = "${var.lambda_description}"
44+
layers = ["${aws_lambda_layer_version.logging_base.arn}"]
45+
46+
function_name = "${var.lambda_func_name}-${var.sns_topic_name}"
47+
description = "${length(var.lambda_description) > 0 ? var.lambda_description : local.dynamic_description}"
1848

19-
filename = "${path.module}/source.zip"
20-
source_code_hash = "${base64sha256(file("${path.module}/source.zip"))}"
49+
filename = "${path.module}/lambda.zip"
50+
source_code_hash = "${data.archive_file.lambda_function.output_base64sha256}"
2151

2252
publish = "${var.lambda_publish_func ? 1 : 0}"
2353
role = "${aws_iam_role.lambda_cloudwatch_logs.arn}"
2454

25-
runtime = "python2.7"
26-
handler = "lambda_function.lambda_handler"
55+
runtime = "${var.lambda_runtime}"
56+
handler = "sns_cloudwatch_gw.main"
2757
timeout = "${var.lambda_timeout}"
2858
memory_size = "${var.lambda_mem_size}"
2959

@@ -126,13 +156,13 @@ resource "aws_lambda_permission" "sns_cloudwatchlog" {
126156

127157
# Create IAM role
128158
resource "aws_iam_role" "lambda_cloudwatch_logs" {
129-
name = "lambda_${lower(var.lambda_func_name)}"
159+
name = "lambda-${lower(var.lambda_func_name)}-${var.sns_topic_name}"
130160
assume_role_policy = "${data.aws_iam_policy_document.lambda_cloudwatch_logs.json}"
131161
}
132162

133163
# Add base Lambda Execution policy
134164
resource "aws_iam_role_policy" "lambda_cloudwatch_logs_polcy" {
135-
name = "lambda_${lower(var.lambda_func_name)}_policy"
165+
name = "lambda-${lower(var.lambda_func_name)}-policy-${var.sns_topic_name}"
136166
role = "${aws_iam_role.lambda_cloudwatch_logs.id}"
137167
policy = "${data.aws_iam_policy_document.lambda_cloudwatch_logs_policy.json}"
138168
}
@@ -170,7 +200,7 @@ data "aws_iam_policy_document" "lambda_cloudwatch_logs_policy" {
170200
resource "aws_cloudwatch_event_rule" "warmer" {
171201
count = "${var.create_warmer_event ? 1 : 0}"
172202

173-
name = "sns_logger_warmer"
203+
name = "sns-logger-warmer-${var.sns_topic_name}"
174204
description = "Keeps ${var.lambda_func_name} Warm"
175205
schedule_expression = "rate(15 minutes)"
176206
}

outputs.tf

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# -----------------------------------------------------------------
1+
# ----------------------------------------------------------------
22
# AWS SNS TO CLOUDWATCH LOGS LAMBDA GATEWAY - OUTPUTS
3-
# -----------------------------------------------------------------
3+
# ----------------------------------------------------------------
44

55
output "lambda_name" {
66
description = "Name assigned to Lambda Function."

source.zip

-10.2 MB
Binary file not shown.

variables.tf

+7-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ variable lambda_func_name {
5858

5959
variable lambda_description {
6060
type = "string"
61-
default = "Route SNS messages to CloudWatch Logs"
61+
default = ""
6262
description = "Description to assign to Lambda Function."
6363
}
6464

@@ -82,6 +82,12 @@ variable lambda_mem_size {
8282
description = "Amount of RAM (in MB) assigned to the function. The default (and minimum) is 128MB, and the maximum is 3008MB."
8383
}
8484

85+
variable lambda_runtime {
86+
type = "string"
87+
default = "python3.6"
88+
description = "Lambda runtime to use for the function."
89+
}
90+
8591
variable "lambda_tags" {
8692
description = "A mapping of tags to assign to Lambda Function."
8793
default = {}

0 commit comments

Comments
 (0)