はじめに
CloudWatch Logsで集めたログの中で任意の文字列(例えば、Errorとか、Criticalとか)が記載されていた場合、メールなどで通知させたい事がある。
Node.jsをLambdaで動かす事で文字列監視を実装した。
通知先の作成
まずはSNSでメールの宛先から作成しARNを控え、エンドポイントとなるメールアドレスを設定する。
node.js(lambda)
関数コードを編集
ERROR、CRITICALという文字列があったら監視するスクリプト
var zlib = require('zlib'); var aws = require('aws-sdk'); var sns = new aws.SNS({ region: 'ap-northeast-1' }); exports.handler = function(input, context, callback) { var data = new Buffer(input.awslogs.data, 'base64'); zlib.gunzip(data, function(e, rst) { if (e) { callback(e); } else { rst = JSON.parse(rst.toString('utf-8')); var errL = rst['logEvents'] .filter(function(evt) { return evt['message'].match(/ERROR/i) ;}) .filter(function(evt) { return !evt['message'].match(/$^/) ;}) .map(function(evt) { return evt['message'] }); console.log('processing[Error]' + errL.length + '/' + rst['logEvents'].length + ' events.'); var critL = rst['logEvents'] .filter(function(evt) { return evt['message'].match(/CRITICAL/i) ;}) .filter(function(evt) { return !evt['message'].match(/$^/) ;}) .map(function(evt) { return evt['message'] }); console.log('processing[Crit]' + critL.length + '/' + rst['logEvents'].length + ' events.'); if (errL.length === 0 && critL.length === 0) { callback(); return; } var date = new Date(); date.setTime(date.getTime() + 1000*60*60*9); var dateTime = date.getFullYear() + '/' + ("0" + (date.getMonth() + 1)).slice(-2) + '/' + ("0" + date.getDate()).slice(-2) + ' ' + ("0" + date.getHours()).slice(-2) + ':' + ("0" + date.getMinutes()).slice(-2) + ':' + ("0" + date.getSeconds()).slice(-2); if (0 < errL.length) { // has error log var sjct = '[Error] Notify From CloudWatch Logs'; var pl = { default: '' }; pl['default'] += 'NotifyAt: ' + dateTime.valueOf() + '\n'; pl['default'] += 'Log: ' + rst['logGroup'] + ' - ' + rst['logStream'] + '\n'; pl['default'] += 'Filter: ' + rst['subscriptionFilters'] + '\n'; pl['default'] += 'Messages:\n'; pl['default'] += errL.join('\n---\n'); sns.publish({ Subject: sjct, Message: JSON.stringify(pl), MessageStructure: 'json', TargetArn: 'arn:aws:sns:ap-northeast-1:1234567890(your no):(your arn)' }, function(err, data) { if (err) { callback(err); } else if (0 < critL.length) { // has waring too var sjct = '[Critical] Notify From CloudWatch Logs'; var pl = { default: '' }; pl['default'] += 'NotifyAt: ' + dateTime.valueOf() + '\n'; pl['default'] += 'Log: ' + rst['logGroup'] + ' - ' + rst['logStream'] + '\n'; pl['default'] += 'Filter: ' + rst['subscriptionFilters'] + '\n'; pl['default'] += 'Messages:\n'; pl['default'] += critL.join('\n---\n'); sns.publish({ Subject: sjct, Message: JSON.stringify(pl), MessageStructure: 'json', TargetArn: 'arn:aws:sns:ap-northeast-1:1234567890(your no):(your arn)' }, function(err, data) { if (err) callback(err); else callback(null, data); }); } else { callback(null, data); } }); } else { // has NOT error log == criticaling only var sjct = '[Critical] Notify From CloudWatch Logs'; var pl = { default: '' }; pl['default'] += 'NotifyAt: ' + dateTime.valueOf() + '\n'; pl['default'] += 'Log: ' + rst['logGroup'] + ' - ' + rst['logStream'] + '\n'; pl['default'] += 'Filter: ' + rst['subscriptionFilters'] + '\n'; pl['default'] += 'Messages:\n'; pl['default'] += critL.join('\n---\n'); sns.publish({ Subject: sjct, Message: JSON.stringify(pl), MessageStructure: 'json', TargetArn: 'arn:aws:sns:ap-northeast-1:1234567890(your no):(your arn)' }, function(err, data) { if (err) callback(err); else callback(null, data); }); } } }); };
トリガーを設定
今回はCloudWatch Logsがトリガーとなるので、CloudWatch Logsを選択し、その後対象のログを選択する。
通知先の設定
Amazon SNSのARNを選択する(予めSNSでトピックを作っておく必要がある)
以上