背景
最近研究cloudwatch实现邮件告警,流程是 cloudwatch --> sns --> email,但是存在一个问题,邮件只在告警被触发的时候发一次,于是想到给现有的监控系统加一个回调,让sns通过post把告警内容发到监控系统,由监控系统来告警,回头一看监控系统是php写的,那就接着用php往上补吧。
PHP内置webserver
测试个小功能,php内置的webserver已经可以满足要求了,省去了安装nginx或apache的步骤
编写index.php文件
public function sns(){
try{
$data = json_decode(file_get_contents(‘php://input‘), true);
}catch (Exception $e){
$res[‘retCode‘] = 255;
$res[‘message‘] = $e->getMessage();
echo json_encode($res);
exit();
}
# The first time to configure sns http url, confirm the subscription is needed.
if (array_key_exists(‘Type‘,$data) && $data[‘Type‘] == ‘SubscriptionConfirmation‘){
$content = file_get_contents($data["SubscribeURL"]);
exit();
}
$alarm = array();
$alarm[‘space_uuid‘] = ‘uuid‘;
$alarm[‘token‘] = ‘token‘;
$alarm[‘category‘] = ‘category‘;
$alarm[‘checktime‘] = time();
# Cloudwatch has no severity settings, so set it to critical default, if event recovery, set status 0.
if ($data[‘NewStateValue‘] == ‘OK‘){
$alarm[‘status‘] = ‘0‘;
}else{
$alarm[‘status‘] = ‘2‘;
}
$alarm[‘service‘] = $data[‘Trigger‘][‘MetricName‘];
$account = $data[‘AWSAccountId‘];
$region = split(‘:‘,$data[‘AlarmArn‘])[3];
$namespace = $data[‘Trigger‘][‘Namespace‘];
$NewStateReason = $data[‘NewStateReason‘];
$Dimensions = ‘‘;
foreach ($data["Trigger"]["Dimensions"] as $v) {
$dimension = implode(‘-‘,$v);
$Dimensions = $Dimensions . ‘ ‘ . $dimension;
}
$alarm[‘tags‘] = sprintf("%s_%s_%s", $account, $region, $namespace);
$alarm[‘message‘] = sprintf("AlertReason:%s. Info:%s", $NewStateReason, $Dimensions);
try{
$ret = $this->postData($this->dutyApi, $alarm);
$ret = json_decode($ret, true);
$status = $ret[‘status‘];
$message = $ret[‘message‘];
}catch (Exception $e){
$res[‘retCode‘] = 255;
$res[‘message‘] = $e->getMessage();
echo json_encode($res);
exit();
}
if($status == 1){
$res[‘retCode‘] = 0;
$res[‘message‘] = $message;
}else{
$res[‘retCode‘] = 255;
$res[‘message‘] = $message;
}
echo json_encode($res);
}
启动服务
[root@alex stoneguo1993]# php -S 0.0.0.0:80
PHP 5.4.16 Development Server started at Thu Sep 24 10:32:10 2020
Listening on http://0.0.0.0:80
Document root is /home/stoneguo1993
Press Ctrl-C to quit.
post数据并测试结果
curl -X POST http://34.96.xx.xx -d ‘{"AlarmName":"awsec2-i-0934fxxxxxx-GreaterThanOrEqualToThreshold-CPUUtilization","AlarmDescription":"Created from EC2 Console","AWSAccountId":"13143xxxxxx","NewStateValue":"ALARM","NewStateReason":"Threshold Crossed: 1 out of the last 1 datapoints [7.48624681823933 (23/09/20 09:02:00)] was greater than or equal to the threshold (1.0) (minimum 1 datapoint for OK -> ALARM transition).","StateChangeTime":"2020-09-23T09:07:54.973+0000","Region":"US West (Oregon)","AlarmArn":"arn:aws:cloudwatch:us-west-2:1314xxxxxx:alarm:awsec2-i-0934faxxxxxx-GreaterThanOrEqualToThreshold-CPUUtilization","OldStateValue":"OK","Trigger":{"MetricName":"CPUUtilization","Namespace":"AWS/EC2","StatisticType":"Statistic","Statistic":"AVERAGE","Unit":null,"Dimensions":[{"value":"i-0934fa2xxx","name":"InstanceId"}, {"value":"prod","name":"env"}],"Period":300,"EvaluationPeriods":1,"ComparisonOperator":"GreaterThanOrEqualToThreshold","Threshold":1.0,"TreatMissingData":"","EvaluateLowSampleCountPercentile":""}}‘
返回值符合预期
Array
(
[space_uuid] => this is uid
[token] => this is token
[category] => this is category
[checktime] => 1600943640
[status] => 2
[service] => CPUUtilization
[tags] => 1314xxxxx_us-west-2_AWS/EC2
[message] => AlertReason:Threshold Crossed: 1 out of the last 1 datapoints [7.48624681823933 (23/09/20 09:02:00)] was greater than or equal to the threshold (1.0) (minimum 1 datapoint for OK -> ALARM transition).. Info: i-0934faxxxxxx-InstanceId prod-env
)
拓展
用python获取sns发过来的数据
import json
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route(‘/‘, methods=[‘GET‘, ‘POST‘])
def parse_request():
data = json.loads(request.data)
print(data)
return data