AWS
twilio
SNS
lambda

アラート発生時に AWS Lambda を使って音声電話をかける

More than 3 years have passed since last update.

続編: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」から「電話番号」に進み、電話番号を購入します。
購入した電話番号は後で使うので、メモしておきます。

Twilio_User_-_Account_Phone_Numbers_Incoming.png

050から始まる番号であれば、月額108円で安いです。監視用なので、これで十分です。

API 用認証情報の確認

アカウントメニューから「アカウント」を選択すると、REST API 用の認証情報が表示されます。
ここに表示される AccountSID および AuthToken は後で使うので、メモしておきます。

Twilio_User_-_Account_Settings.png

Lambda function の作成

リージョンを N.Virginia に切り替え、Lambda で新規に function を作成します。

AWS_Lambda.png

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 は、こんな感じで。

TwiML.xml
<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 を割り当てられます。

AWS_Lambda.png

SNS の管理画面から「Create Subscription」を選び、Protocol を「AWS Lambda」に、Endpoint にコピーした Function ARN を入れれば完了です。

AWS_SNS.png

これで、Amazon SNS に通知が来ると、AWS Lambda の function が実行され、Twilio API が呼び出されて電話がかかってきます。

応用

Twilio で電話をかけるには、TwiML で記述された XML を準備する必要があります。
この例では固定の文言を喋らせていますが、動的なメッセージを喋らせる場合は、S3 にメッセージを都度出力し、その URL を渡すようにするなどの工夫が必要です。
また、Twilio はステータス受信用のコールバック API を定義できますので、電話に出なかった場合などは次の人に電話をかける、等の処理を行ってみるのもいいかと思います。

続編:SNS + Lambda + Twilio で音声電話をかける v2


  • 7/1
    • AWS Lambda が東京リージョンで利用可能になったので、一部修正