Event Streamsを用いてTwilioのログをNode.jsとExpressサーバーアプリケーションで処理する方法
読む所要時間: 12 分

Twilioは音声通話、SMS、ビデオなどさまざまなコミュニケーションAPIを提供しています。それぞれのAPIの実行結果はstatusCallback
、あるいは類似したプロパティにコールバックURLを設定することでアプリケーション側にログを通知し、分析やエラー処理を行えるようになっています。
例 - Programmable SMS API(statusCallbackで検索)
このコールバックは簡単に利用できますが、複数のTwilioサービスを利用する場合はサービスごとあるいはリクエストごとに指定する必要があります。さらに、ログのフォーマットもサービスごとに異なる場合があります。
Event Streamsは各サービスのログをCloudEventsの仕様に沿って正規化、集約し、指定した宛先に配信します。そのためサービスごとに複数のコールバックを指定する必要がなく、またログの処理やエラーハンドリングをより簡単に実装できます。今回はこのEvent StreamsをNode.js/Expressサーバーアプリケーションで利用する方法を紹介します。また、Event Streamsの特長についてはこちらの記事で取り上げられていますのでぜひご覧ください。
前提条件
このチュートリアルを試すには次の環境が必要になります。
- Node.js および npm(Node.jsインストールパッケージに同梱)
- Twilioアカウント(アカウントの作成方法)
- ngrok(Qiita - ngrokが便利すぎる)
- コードエディタ
イベントデータを受け取るExpressサーバーアプリケーションを構築
まず、イベントデータを受け取るExpressアプリケーションを作成します。
コンソールを開き、以下のコマンドをそれぞれ実行します。
続けてExpressパッケージをインストールします。
この状態でindex.js
ファイルを作成し、次のコードを追加します。
index.js
ではExpressサーバーを初期化し、/events
ルートを実装しています。/events
ルートではリクエストのbody
をコンソールに出力し、ステータスコード200
を返します。
そしてこのコードの最終行では、ローカルホストのポート3000
番でリクエストを待つように実装しています。
続いてターミナルを開きExpressサーバーアプリケーションを起動します。
この状態で http://localhost:3000/events
をブラウザーで開き、OK
と出力されることを確認します。

Event StreamsからこのExpressサーバーアプリケーションにイベントを送信するには外部からアクセスできる必要があります。そのため別のターミナルを開き、下記のngrokコマンドを実行し3000番のポートを外部に公開します。

ランダムに生成されたURL/events
(画像の例ではhttps://49149f5418d7.ngrok.io/events
)をブラウザーで開き、先ほどと同じ結果が得られることを確認しましょう。このURLはEvent Streamsの設定に必要になります。ngrokを再起動するとURLが変更されてしまうため、以後、チュートリアルを完了するまで ngrokを起動したまま にしておいてください。
新しいコンソールでEvent Streamsを設定
Event Streamsを利用するためにはSink
と呼ばれるイベントの配信先を作成する必要があります。これまではTwilio CLIを用いて各種設定を行う必要がありましたが、先日、新しいコンソールから直感的に設定できるようになりました。
Twilioコンソールから、Event Streams
を選択します。

管理画面でCreate new sink
ボタンをクリックし、新しいSinkを作成します。

新規作成画面では、Sinkの説明とSink Typeを指定します。今回のチュートリアルではそれぞれSink tutorial
、Webhook
を設定・選択します。

Next step
ボタンをクリックするとWebhook Sinkの設定画面に遷移します。この画面ではそれぞれ次の設定を行えます。
項目名 |
説明 |
設定値 |
Destination |
イベントの配信先 |
先ほどngrokによって生成されたURL/events |
Method |
Destinationにイベントを送信する際のリクエストメソッド |
POST |
Batch |
イベントをまとめて (Batchで) 送信するかどうか |
True |

項目を入力し、Finish
ボタンをクリックするとSinkが作成されます。ここでダイアログが表示され、Validate sink connection
をクリックするとSinkへの接続をテストできます。

配信先との接続を確認
接続確認ページではテストイベントを発行し、指定したDestination
にイベントが送信されているかどうかを確認できます。

Send test event
ボタンをクリックするとテストイベントが発行されます。実行中のExpressサーバーアプリケーションでテストイベントが出力されていることを確認してください。

dataに含まれるtest_id
の値を先ほどの接続確認ページのTest event ID
フィールドに入力し、Validate connection
ボタンをクリックすると検証が行われます。test_id
が正しいものである場合は接続確認が完了します。

webhookを利用する場合、この接続確認は必須ではありませんが、確認しておくに越したことはないでしょう。
続けてCreate subscription
ボタンをクリックしイベントの購読設定を行います。
イベントの購読
Subscription description
フィールドに任意の名前を入力し、次にどのイベントを購読するかを設定します。
2021年9月時点でEvent Streamsはこちらのイベントに対応しています。今回はSMSを送信するイベントを取得してみましょう。Messaging
のMessage
についてApply schema version to all
項目を1
と設定します。

Create Subscription
ボタンを押して設定を反映します。
これでコンソール側の設定が完了しました。
SMSを送信し、Event Streamsをテスト!
ここからはSMSを送信しイベントが正しくExpressサーバーアプリケーションに配信されていることを確認します。
まずは、電話番号コンソールからSMS送信が可能な米国電話番号を購入します。すでに電話番号を持っている場合は一覧が表示されます

SMS送信可能な番号を保有していない場合は、Buy a number
ボタンをクリックします。
米国を選択し、番号一覧からSMS
を提供している番号を一つ購入します。

購入した番号を控えておきます。
Webアプリケーションの開発環境へと戻り、twilio-nodeヘルパーライブラリーをプロジェクトに追加します。
パッケージのインストール後、sendSMS.js
ファイルを作成し次のコードを追加します。
account_sid
とauth_token
に入力する値はTwilioコンソールで確認できます。

続けてtwilio_number
には先ほど購入したSMS送信可能なTwilio番号を、my_number
には検証済みの送信先電話番号をそれぞれE.164フォーマットで入力します。
それぞれの変数に値を入力した後、新しいターミナルを開き次のコマンドを実行します。
SMSの送信に合わせてExpressサーバーアプリケーションに各種イベントが通知されます。出力を確認しましょう。下記の画像はいくつかの情報を白塗りしていますが、com.twilio.messaging.message.sent
とcom.twilio.messaging.message.delivered
イベントが配信されていることを確認できます。
