本节创建lambda 2,用于输出监控的告警信息。
进入IAM页面,创建Role:
信任主体选择Lambda
:
搜索以下Policy,并全部赋予给这个Role:
CloudWatchFullAccess # Describe / Create / Drop CloudWatch alarms
AWSLambdaRole # Invoke Lambda Function
AmazonSNSFullAccess # Publish SNS messages
AWSLambdaExecute # Put Logs in S3
AmazonRDSFullAccess # Describe / Alter RDS Attributes, Add Tags to RDS
角色名称:lambdaExecRole-autoCreateCxCwAlarms_RDS
点击Create Role
创建Role
进入Lambda页面,创建Lambda:
为Lambda命名为alarm-sender
, runtime选择Python3.9
选择使用上一步创建的Role:
将以下内容粘帖到函数体,第89行,替换成上一节创建的SNS ARN
并点击Deploy
进行部署:
import json
import urllib
import datetime
import dateutil.tz
import re
import boto3
import os
def changeAlarmToLocalTimeZone(event, timezoneCode, localTimezoneInitial, platform_endpoint):
tz = dateutil.tz.gettz(timezoneCode)
# exclude the Alarm event from the SNS records
AlarmEvent = json.loads(event['Records'][0]['Sns']['Message'])
# extract event data like alarm name, region, state, timestamp
alarmName = AlarmEvent['AlarmName']
descriptionexist = 0
if "AlarmDescription" in AlarmEvent:
description = AlarmEvent['AlarmDescription']
descriptionexist = 1
reason = AlarmEvent['NewStateReason']
region = AlarmEvent['Region']
state = AlarmEvent['NewStateValue']
previousState = AlarmEvent['OldStateValue']
timestamp = AlarmEvent['StateChangeTime']
Subject = event['Records'][0]['Sns']['Subject']
alarmARN = AlarmEvent['AlarmArn']
RegionID = alarmARN.split(":")[3]
AccountID = AlarmEvent['AWSAccountId']
# get the datapoints substring
pattern = re.compile('\[(.*?)\]')
# test if pattern match and there is datapoints
if pattern.search(reason):
Tempstr = pattern.findall(reason)[0]
# get in the message all datapoints timestamps and convert to localTimezone using same format
pattern = re.compile('\(.*?\)')
m = pattern.finditer(Tempstr)
for match in m:
Tempstr = match.group()
tempStamp = datetime.datetime.strptime(Tempstr, "(%d/%m/%y %H:%M:%S)")
tempStamp = tempStamp.astimezone(tz)
tempStamp = tempStamp.strftime('%d/%m/%y %H:%M:%S')
reason = reason.replace(Tempstr, '(' + tempStamp + ')')
# convert timestamp to localTimezone time
timestamp = timestamp.split(".")[0]
timestamp = datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S")
localTimeStamp = timestamp.astimezone(tz)
localTimeStamp = localTimeStamp.strftime("%A %B, %Y %H:%M:%S")
# create Custom message and change timestamps
customMessage = 'You are receiving this email because your Amazon CloudWatch Alarm "' + alarmName + '" in the ' + region + ' region has entered the ' + state + ' state, because "' + reason + '" at "' + localTimeStamp + ' ' + localTimezoneInitial + '.'
# Add Console link
customMessage = customMessage + '\n\n View this alarm in the AWS Management Console: \n' + 'https://' + RegionID + '.console.aws.amazon.com/cloudwatch/home?region=' + RegionID + '#s=Alarms&alarm=' + urllib.parse.quote(
alarmName)
# Add Alarm Name
customMessage = customMessage + '\n\n Alarm Details:\n- Name:\t\t\t\t\t\t' + alarmName
# Add alarm description if exist
if (descriptionexist == 1): customMessage = customMessage + '\n- Description:\t\t\t\t\t' + description
customMessage = customMessage + '\n- State Change:\t\t\t\t' + previousState + ' -> ' + state
# Add alarm reason for changes
customMessage = customMessage + '\n- Reason for State Change:\t\t' + reason
# Add alarm evaluation timeStamp
customMessage = customMessage + '\n- Timestamp:\t\t\t\t\t' + localTimeStamp + ' ' + localTimezoneInitial
# Add AccountID
customMessage = customMessage + '\n- AWS Account: \t\t\t\t' + AccountID
# Add Alarm ARN
customMessage = customMessage + '\n- Alarm Arn:\t\t\t\t\t' + alarmARN
# push message to SNS topic
response = platform_endpoint.publish(
Message=customMessage,
Subject=Subject,
MessageStructure='string'
)
# Get SNS Topic ARN from Environment variables
NotificationSNSTopic = os.environ['NotificationSNSTopic']
# Get timezone corresponding to your localTimezone from Environment variables
timezoneCode = os.environ['TimeZoneCode']
# Get Your local timezone Initials, E.g UTC+2, IST, AEST...etc from Environment variables
localTimezoneInitial = os.environ['TimezoneInitial']
# Get SNS resource using boto3
SNS = boto3.resource('sns')
# Specify the SNS topic to push message to by ARN
platform_endpoint = SNS.PlatformEndpoint(NotificationSNSTopic)
def lambda_handler(event, context):
# Call Main function
changeAlarmToLocalTimeZone(event, timezoneCode, localTimezoneInitial, platform_endpoint)
可以使用以下JSON作为测试事件:
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:lambda:us-west-2:532134256174:function:CustomizeCloudWatchAlarmsNotifications-RDS_DatabaseConnections",
"Sns": {
"Type": "Notification",
"MessageId": "f9f5ed56-3d38-57c8-b4ea-b51588f5f871",
"TopicArn": "arn:aws:sns:us-west-2:532134256174:customizedAlarmAction-RDS_DatabaseConnections",
"Subject": "ALARM: \"Test LocalTime\" in China, Asia (Hong Kong)",
"Message": "{\"AlarmName\":\"RDS_DatabaseConnections\",\"AlarmDescription\":\"Auto-created customized CloudWatch Alarm <RDS_DatabaseConnections>\",\"AWSAccountId\":\"532134256174\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: 1 out of the last 1 datapoints [0.0 (04/12/20 03:56:00)] was greater than or equal to the threshold (0.0) (minimum 1 datapoint for OK -> ALARM transition).\",\"StateChangeTime\":\"2020-12-04T03:57:01.659+0000\",\"Region\":\"US West (Oregon)\",\"AlarmArn\":\"arn:aws:cloudwatch:us-west:532134256174:alarm:RDS_DatabaseConnections LocalTime\",\"OldStateValue\":\"OK\",\"Trigger\":{\"Period\":60,\"EvaluationPeriods\":1,\"ComparisonOperator\":\"GreaterThanOrEqualToThreshold\",\"Threshold\":0.0,\"TreatMissingData\":\"- TreatMissingData: missing\",\"EvaluateLowSampleCountPercentile\":\"\",\"Metrics\":[{\"Expression\":\"FILL(m1, 0)\",\"Id\":\"e1\",\"Label\":\"Expression1\",\"ReturnData\":true},{\"Id\":\"m1\",\"MetricStat\":{\"Metric\":{\"Dimensions\":[{\"value\":\"API\",\"name\":\"Type\"},{\"value\":\"DescribeAlarms\",\"name\":\"Resource\"},{\"value\":\"CloudWatch\",\"name\":\"Service\"},{\"value\":\"None\",\"name\":\"Class\"}],\"MetricName\":\"CallCount\",\"Namespace\":\"AWS/Usage\"},\"Period\":60,\"Stat\":\"Average\"},\"ReturnData\":false}]}}",
"Timestamp": "2020-12-04T03:57:01.702Z",
"SignatureVersion": "1",
"Signature": "WcgVMPrlQsJY3yqbds968tqKPC6KKDWHSjIwEmzKVHZYg6foN9F5sm2Tp5IWPgaM9wMmYg8dpQjkxSm4q9V9iP1PbLp81RgJS2NghdeHNVnyxyzywXFMDztYZpgB2pjzfT101RVGpUwVPntOpBeBq2KAs/NrFX1nS2aTK/OX+gyOxwYZxRftzd+ttHA+PCh0kKlym7nnxaWuO9hgSrnupH2YttuvsdTSAOZ4MGhBON/sMmmlcxzfiFD+jJaqlHFmQ0DncjSe1NNwceOpwNsue6//sMYU1QzV6bO34I343KmQdXYw/KISDz7qH70Odm7nRLN3ExSOhtC/FS0/dXGl4Q==",
"SigningCertUrl": "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem",
"UnsubscribeUrl": "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:532134256174:customizedAlarmAction-RDS_DatabaseConnections",
"MessageAttributes": {}
}
}
]
}
创建测试:
将上面的json粘帖进来,并为event命名:
创建完成后,再次点击Test
:
在邮箱中收到对应的告警邮件: