続編:SNS + Lambda + Twilio で音声電話をかける v2
CloudWatch や独自ツールから Amazon SNS に Notification を飛ばすと、subscribe しているメールアドレスにメール通知が行えます。
サービスの監視を行ってアラートをメールで受信しているケースが多いと思いますが、深夜等でメールを受信しても気づかないケースがあり、障害検知が遅れてしまう、という問題があります。
これを回避するために、電話をかけることにしてみました。
電話をかけるのに使うサービスは Twilio。日本ではKDDIが業務提携してサービスを提供しています。
Amazon SNS から AWS Lambda への通知が可能になっていますので、Lambda を使って実装します。
Lambda は現時点で東京リージョンでは使えないため、N.Virginia を使います。
7/1 修正: 東京リージョンでも利用可能になりました。
Twilio の設定
電話番号の購入
Twilio にサインアップし、発信用の電話番号を購入します。
「VOICE, SMS & MMS」から「電話番号」に進み、電話番号を購入します。
購入した電話番号は後で使うので、メモしておきます。
050から始まる番号であれば、月額108円で安いです。監視用なので、これで十分です。
API 用認証情報の確認
アカウントメニューから「アカウント」を選択すると、REST API 用の認証情報が表示されます。
ここに表示される AccountSID
および AuthToken
は後で使うので、メモしておきます。
Lambda function の作成
リージョンを N.Virginia に切り替え、Lambda で新規に function を作成します。
Role には、特にこれまでに作成していなければ、「Basic execution role」を選択して新規に作成します。
以下、Twilio API を呼び出す JS コードです。
先ほどメモした発信用の電話番号および、認証情報を埋めてください。
var accountSid = 'YOUR_TWILIO_ACCOUNT_SID';
var authToken = 'YOUR_TWILIO_AUTH_TOKEN';
var fromNumber = '+81XXXXXXXXXX';
var toNumber = '+81XXXXXXXXXX';
var configUrl = 'http://YOUR.HOST/PATH/TO/TwiML.xml';
var https = require('https');
var queryString = require('querystring');
exports.handler = function (event, context) {
console.log('Start twilio call');
callTwilio(function(status) {
context.done(null, status);
});
};
function callTwilio(callback) {
var messageString = queryString.stringify({
From: fromNumber,
To: toNumber,
Url: configUrl,
Method: 'GET'
});
var options = {
host: 'api.twilio.com',
port: 443,
path: '/2010-04-01/Accounts/' + accountSid + '/Calls.json',
method: 'POST',
headers: {
'Authorization': 'Basic ' + new Buffer(accountSid + ':' + authToken).toString('base64'),
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(messageString)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf-8');
var responseString = '';
res.on('data', function(data) {
responseString += data;
});
res.on('end', function() {
console.log('Twilio Response: ' + responseString);
callback('API request sent successfully.');
});
});
req.on('error', function(e) {
console.error('HTTP error: ' + e.message);
callback('API request completed with error(s).');
});
console.log('Twilio API call: ' + messageString);
req.write(messageString);
req.end();
}
configUrl
で指定する TwiML は、こんな感じで。
<Response>
<Say language="ja-JP" voice="alice">これはアラート通知テストです。</Say>
<Pause length="1"/>
<Say language="ja-JP" voice="alice">詳細は XXXX までお問い合わせください。</Say>
</Response>
voice="alice"
だと女性の声で喋ってくれます。日本語文章も問題なく喋ってくれますが、クオリティはまだ低いのであまり嬉しくはありません。。
Amazon SNS との連携
Lambda の Function list に戻ると、作成した fcuntion が現れています。ARN をコピーし、Amazon SNS の管理画面に移動します。
恐らく同一リージョンであれば「Actions」の「Add event source」から SNS の Topic を選べるのでしょうが、Lambda と SNS のリージョンが異なるからか、候補リストに何も表示されないため、SNS 側から設定します。
7/1 追記:東京リージョンで Function を作成すれば、「Add event source」で SNS の Topic を割り当てられます。
SNS の管理画面から「Create Subscription」を選び、Protocol を「AWS Lambda」に、Endpoint にコピーした Function ARN を入れれば完了です。
これで、Amazon SNS に通知が来ると、AWS Lambda の function が実行され、Twilio API が呼び出されて電話がかかってきます。
応用
Twilio で電話をかけるには、TwiML で記述された XML を準備する必要があります。
この例では固定の文言を喋らせていますが、動的なメッセージを喋らせる場合は、S3 にメッセージを都度出力し、その URL を渡すようにするなどの工夫が必要です。
また、Twilio はステータス受信用のコールバック API を定義できますので、電話に出なかった場合などは次の人に電話をかける、等の処理を行ってみるのもいいかと思います。
続編:SNS + Lambda + Twilio で音声電話をかける v2
- 7/1
- AWS Lambda が東京リージョンで利用可能になったので、一部修正