メールを送ると即時電話通報するZap(Email by Zapier)

# 概要

Zapierの「Email by Zapier」で生成したメールアドレス宛てにメールを送ると、Twilioで電話がかかってくるようになり、さらにおまけでSlack通知するZapについて記述しています。


# これまでの背景と課題

1. システム監視でアラートが発生した際にメール通知は実施していたが、すぐに気付ける仕組みではなかった。

2. 監視オペレータがクリティカルなアラートを確認した直後に、連絡網にそってシステム管理者に電話をかけるようになっていたが、1人ずつにしか電話をかけられないため、1人目に1回で電話がつながらない場合は、何人も何回も電話をかけなければならず、障害に対応着手できるまでのタイムラグが長かった。

3. アラート内容をSlackへ通知するようになってからは、すぐに情報を拾える仕組みはできたが、@channelメンションなどを用いても、すぐに気付ける仕組みにはならなかった。（業務時間中でSlackを常駐起動している場合は気付けるが、業務時間外の場合にモバイルのプッシュ通知では気づきにくい）

4. Twilioで電話通報の仕組みを用意しようとしたが、APIをキックして電話通報を実行させるための仕組みに悩んだ。監視システムは複数あり、それぞれの環境下の制約をクリアしていくのは現実的ではなかったため。

5. そこで、Slackに通知された内容をBotが拾って、TwilioのAPIを実行するようにしたが、通報先リストがワンパターンになってしまった。分岐させるにはBotを作り込めばよかったが、今後の保守が面倒で手がつかなかった。

6. また「監視システム　→　Slack　→　Bot　→　Twilio　→　電話通報」とフローが長くなり過ぎて、どこか一箇所で止まると動かなくなるので、シンプルな仕組みが欲しかった。

**→そこで、費用面・保守性・拡張性を考慮して、Zapierを導入することにしました。**


# Zapier導入後の構成とメリット

**構成：　監視システム　→（メール）→　Zapier　→　Twilio →（電話通報）**

* 各監視システムは、これまでのメール通知と同じようにZapierに送信するメールアドレスが1つ増えるだけなので、特別な対応は不要。

* 個人のメールボックスをポーリングするZapierの標準のトリガー（5分間隔）ではなく、「Email by Zapier」はメールを受信したら即時トリガーが反応する「インスタントトリガー」なので、障害発生〜電話通報までの時間が圧倒的に短縮された。

* トリガーのメールアドレスはいくつでも作成でき、メールアドレスも認識しやすいよう独自の文字列で作成できる。　※「自由文字列＋固定文字列＠Zapierドメイン」というメールアドレスになります。
 
* Twilioの電話の通報先をZapier上で手軽に設定できるようになった。（一元管理）


# ZapierのZap全体フロー

![zapier_com_app_editor_42677897_overview.png](https://qiita-image-store.s3.amazonaws.com/0/148986/0f7557c9-159a-4264-82aa-7427f1d0c2bc.png)

## 解説
1.TRIGGER: New Inbound Email
　トリガーとなるメールアドレスを設定する。
↓
2.ACTION: Date/Time
　メールの送信日時をUNIX時間に変換する。
↓
3.ACTION: Numbers
　（現在のUNIX時間）マイナス（2のUNIX時間）を算出する。
↓
4.SEARCH OR CREATE: Get or Set a Value
　ストレージに格納したフラグの値を取得する（なければ作成する）
↓
5.FILTER: Only continue if...
　4で取得したフラグ値が【off】であること（＝Twilio電話通報が実行中ではない＝多重実行を防止）
　3で算出した値が【600】未満であること（＝トリガーとなるメールは10分以内に送信された＝メール遅延による発動を抑止）
　※そのほかにも後続を実行するフィルタ条件を任意で追加。
↓
6.ACTION: Set Value If
　フラグ値が【off】だったら【on】で設定する（多重実行や同時実行を防止）
↓
7.FILTER: Only continue if...
　6で設定したフラグが存在していること（同時実行された場合でも、6の設定は1つしか通過しない）
↓
8.ACTION: Call Phone
　Twilioで電話をかける。
↓
9.ACTION: Send Channel Message
　Slackにトリガーとなったメールの件名を通知する。
↓
10.ACTION: Delay For
　10分間Zapを遅延させる（フラグを【on】にしたままなので、短時間のバースト実行を抑止）
↓
11.ACTION: Set Value If
　フラグが【on】だったら【off】に設定する。


# 各ステップごとの設定について


## 1.TRIGGER: New Inbound Email

対象APPは「Email」
<img width="192" alt="スクリーンショット 2018-09-23 16.18.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/ab564601-41d2-2c1e-ac9d-8af8d8e0bce5.png">
↓
<img width="751" alt="スクリーンショット 2018-09-23 18.35.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/5ee96479-12e7-d8d8-8956-8d3f809ee4a9.png">
↓
<img width="772" alt="スクリーンショット_2018-09-23_16_20_16.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/54e230ba-44cf-2130-e215-2b3ce52c80cd.png">

ここで設定したメールアドレスは後からでも変更が可能ですが、メールアドレスを変更する都度、監視システムの通知先に設定しているメールアドレスも変更しなければいけないので、注意が必要です。


## 2.ACTION: Date/Time

対象APPは「Formatter」
<img width="189" alt="スクリーンショット 2018-09-23 16.27.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/d38f44b5-5a01-9c40-8038-f5388cb9027c.png">
↓
<img width="749" alt="スクリーンショット 2018-09-23 18.34.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/f58f29de-2b5d-d481-7d19-d6bbb33107e1.png">
↓
<img width="769" alt="スクリーンショット 2018-09-23 16.29.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/43edc5b9-4c19-3e2c-3867-d02105184625.png">

メールの送信日時をUNIX時間に変換しています。変換した値は後続のステップ3で利用します。


## 3.ACTION: Numbers

対象APPは「Formatter」
<img width="189" alt="スクリーンショット 2018-09-23 16.27.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/d38f44b5-5a01-9c40-8038-f5388cb9027c.png">
↓
<img width="753" alt="スクリーンショット 2018-09-23 18.35.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/3dcb724c-272e-f7fe-40d7-901629f62604.png">
↓
<img width="769" alt="スクリーンショット 2018-09-23 16.33.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/89818f0d-c93c-9607-4299-a943cf73453d.png">

`{{zap_meta_timestamp}}`は、UNIX時間で変換された現在時刻を表すZapierの定義変数です。（[参考：Modifying Dates & Time](https://zapier.com/help/modifying-dates-and-times/)）

現在時刻からメール送信日時をマイナスすることで、メールが送信されてからの経過秒数を算出しています。算出した値は後続のステップ5で利用します。


## 4.SEARCH OR CREATE: Get or Set a Value

対象APPは「Storage」
<img width="185" alt="スクリーンショット 2018-09-23 16.35.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/aa0fdf96-fba2-4f79-e234-10124ccac0ae.png">
↓
<img width="764" alt="スクリーンショット 2018-09-23 16.35.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/ee075ea8-589d-7e2b-c899-2aa321f2cfbe.png">
↓
<img width="766" alt="スクリーンショット_2018-09-23_16_37_27.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/6a3f9b4a-37ff-2dbb-86e4-b57d1bfc9bf3.png">

障害時にアラートメールが何通も飛ぶことはよくあります、その都度何回もトリガーが発動され電話がなり続けてしまうので、ストレージのkey&valueを活用して、フラグ制御しています。

トリガーとなるメールアドレス1つにつき、フラグを1つ用意しています。
初回だけストレージにまだkeyが存在しないので、初期値【off】で作成するようにしています。


## 5.FILTER: Only continue if...

対象APPは「Filter」
<img width="192" alt="スクリーンショット 2018-09-23 16.40.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/22147164-ee34-1ceb-2d15-15fdda958d21.png">
↓
<img width="757" alt="スクリーンショット 2018-09-23 16.40.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/0faa0a36-051a-c6d7-14bc-6691de73997c.png">
↓
<img width="732" alt="スクリーンショット_2018-09-23_16_41_22.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/df255339-71be-465d-06f5-8a49c1644ab8.png">

電話を通報するかどうかをチェックしています。（1回目）

* 4で取得したフラグ値が【off】であることをチェックすることにより、すでにTwilio電話通報が実行中ではないことを確認します。これにより多重実行を防止しています。
* 
* 3で算出した値が【600】未満であることをチェックすることにより、トリガーとなるメールは10分以内に送信されたことを確認します。メール遅延によって数時間遅れたメールに対して電話通報されないように抑止しています。

※ 画像の真ん中の条件は、私の現場固有の条件なので無視していただいて大丈夫です。
Zabbixの場合、障害通知と回復通知を1つのアクション定義内で設定するため、回復メールが届いた際に電話通報されないように、メールの件名でフィルタをしています。


## 6.ACTION: Set Value If

対象APPは「Storage」
<img width="185" alt="スクリーンショット 2018-09-23 16.35.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/aa0fdf96-fba2-4f79-e234-10124ccac0ae.png">
↓
<img width="758" alt="スクリーンショット 2018-09-23 16.46.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/81c7a41a-5557-27fc-7fe0-d8a03c73f2e0.png">
↓
<img width="760" alt="スクリーンショット 2018-09-23 16.46.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/1288550e-7dd5-29fe-1232-8aac3b057837.png">

電話通報をする前にフラグの値を【off】だったら【on】にします。

同時に複数のトリガーメールを受信した際に、ステップ5のフィルタ条件を同時に通過することがまれにあります。
そのため、ただ値を設定するのではなく、「変更前の値が【off】だったら」という条件を加えることにより、仮にステップ5のフィルタを同時に通過したとしても、ここのアクションが成功するのは1つだけとなります。このアクションの結果はステップ7で利用します。


## 7.FILTER: Only continue if...

対象APPは「Filter」
<img width="192" alt="スクリーンショット 2018-09-23 16.40.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/22147164-ee34-1ceb-2d15-15fdda958d21.png">
↓
<img width="757" alt="スクリーンショット 2018-09-23 16.40.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/0faa0a36-051a-c6d7-14bc-6691de73997c.png">
↓
<img width="719" alt="スクリーンショット_2018-09-23_16_48_28.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/ddada43e-a88f-3a90-06b0-ecd75790476b.png">

電話を通報するかどうかをチェックしています。（2回目）

* 設定値は必ずステップ6のフラグを設定してください。ステップ6が成功した時にのみ、フラグが存在しますので、ステップ5を同時通過した時でも、ここで1つに制限されるようにます。

※設定後の見た目では分かりにくいですが、他のステップの同名フラグでは結果が異なりますのでご注意ください。

※もしステップ6のフラグが設定できない（表示されない）場合は、サンプルデータによるテストがステップ6まで通過していないことになります。テスト用のトリガーメールを再送信して、ステップ6まで成功するサンプルデータを指定した後、ステップ6を再テストしてください。


## 8.ACTION: Call Phone

対象APPは「Twilio」
<img width="189" alt="スクリーンショット 2018-09-23 16.50.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/ca690608-c765-69dd-afeb-2e3afe6e0a35.png">
↓
<img width="760" alt="スクリーンショット 2018-09-23 16.50.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/ce319760-0b86-13ba-b86d-92b346050db3.png">
↓
<img width="771" alt="スクリーンショット_2018-09-23_16_52_11-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/0a8aaf2c-41ac-89ad-f134-ef4a56ad19e9.png">

電話通報します。

電話の着信だけあればよかったので「メッセージ」は空欄にしたかったのですが、必須項目だったため、メッセージには適当な日本語を入力して、言語指定を空欄としています。そうすることで、デフォルトの英語でメッセージを解読しようするので、電話口では何も発声することなく、通話を終了するようになります。

★電話の音声内容を確認するのは時間がかかるし、留守番電話に残った場合にそれを削除する手間が地味に面倒だったので、電話では何も発声させないようにしています。

★音声で詳細を喋らせるよりも、Slackなどに通知されているテキスト情報のほうが情報量が多いためというのもあります。


もし、電話で日本語発声させる場合は、下記のように設定してください。

* Custom Value for Voice: `alice`　
* Custom Value for Language: `ja-JP`

※Twilioで日本語対応しているのがaliceだけのため（2018年9月23日現在）

<img width="765" alt="スクリーンショット 2018-09-23 16.57.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/1a035d40-9a2d-be04-7dcb-a4535f3d9088.png">


## 9.ACTION: Send Channel Message

対象APPは「Slack」
<img width="192" alt="スクリーンショット 2018-09-23 17.05.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/2a8d8e3b-a481-76c4-9222-7e92a163592b.png">
↓
<img width="760" alt="スクリーンショット 2018-09-23 17.06.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/914124c6-fb26-a8a7-0958-0e3b0a1a42f5.png">
↓
<img width="768" alt="スクリーンショット_2018-09-23_17_07_32.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/e6506458-bdce-f76a-3bce-f9c869189427.png">

Slackにトリガーとなったメールの件名を通知しています。

★電話をかけるということだけに着目すると不要なステップですが、電話がかかってきたトリガー要因を確認しやすくするためにSlack通知しています。Zapierのタスクヒストリーを見れば同じ情報は確認可能ですが、Zapierにログインしなくても確認しやすくするためのステップです。


## 10.ACTION: Delay For

対象APPは「Delay」
<img width="193" alt="スクリーンショット 2018-09-23 17.10.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/8bb50ed2-3c38-9d36-3508-131293d8a480.png">
↓
<img width="742" alt="スクリーンショット 2018-09-23 17.10.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/9b9e8799-3fd5-c9aa-00f0-01bbfca15ab4.png">
↓
<img width="762" alt="スクリーンショット 2018-09-23 17.11.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/9d402fe7-afd8-05af-b139-b3a59980d6b2.png">

処理中のZapをここのステップで10分間遅延させています。
この間、フラグは【on】のままなので、仮に短時間で多数のトリガーメールを受信し続けたとしても、フラグが【off】になるまでの10分間は電話がかかってこないので、障害対応者は作業に集中できます。


## 11.ACTION: Set Value If

対象APPは「Storage」
<img width="185" alt="スクリーンショット 2018-09-23 16.35.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/aa0fdf96-fba2-4f79-e234-10124ccac0ae.png">
↓
<img width="758" alt="スクリーンショット 2018-09-23 16.46.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/81c7a41a-5557-27fc-7fe0-d8a03c73f2e0.png">
↓
<img width="765" alt="スクリーンショット 2018-09-23 17.14.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/148986/a84f3933-7b4b-325e-b737-57f31a8f5cb0.png">

すべての処理が終わったのでフラグの値を【on】だったら【off】にします。
以降は、トリガーメールが受信したら、電話通報可能な状態となります。


# 上記のZapを設定する際の注意点

全てのステップを順番にテストしている場合は問題ないですが、部分的にテストしている場合は、フラグの値を【on】にしたままにしてしまう場合があるので、別のZapにて、すべてのフラグの値を確認するZapとすべてのフラグを【off】にリセットするZapがあるといいかもしれません。（手動チェック用）

もっと厳密にする場合は、毎時スケジュール実行でフラグをチェックすると安心です。（自動チェック用）


# 上記のZapを実現するための費用

* ZapierはTeamプランに加入しています。年間契約なので、年間3000ドルです。
* Twilioは、発信元の固定電話番号代が月額108円／1つあたりです。加えて、携帯電話宛に発信するたびに16.2円/分かかっています。

→１か月あたり「250ドル＋108円」（固定）と「16.2円×電話通報数」（従量）となります。これが安いか高いかは現場によりけりだと思うので、ご判断はお任せします。

※Slackの料金は、主旨からそれるため割愛します。


# 残された課題

* 誰が電話に応答したかが確認できないので、仮に深夜に障害が発生して電話通報された際に、誰も応答できない可能性も想定されます。その際に、誰かが応答するまで電話をかけ続けるという仕組みを用意したかったのですが、今のところ解決策は見つかっていません。


# 参考情報

* [Zapierヘルプ](https://zapier.com/help/)
* [Zapier料金](https://zapier.com/pricing/)
* [Twilio料金](https://twilio.kddi-web.com/price/)