🔍

死活監視をGASを使ってSlackへ通知させてみた(前編)

2021/09/19に公開

今回はタイトル通り、死活監視をGASで書いてSlackに通知させてみたよというお話です。
綺麗なまとめというより自分自身の思考の流れも書いています。
※まだまだ知識不足で説明不十分や間違っている部分もあるかと思いますので、
もし気になる点があればコメントいただければと思います。

この記事を読む対象者

・「死活監視」って何?という方
・GASってなに?ガス?ギャス?という方
・JavaScriptは少し触ったことがある方
・GASで書いたものをSlackに通知させてみたい方

死活監視とは?

コンピューターやシステムが正常に稼働しているかどうか、外部から継続的に監視すること

これはWEBサイトの場合、ユーザーから見た場合にサイトが見れない状態だと通知が来るといった流れになるかと思います。
他にも監視のレベルは様々あるかと思いますが、死活監視は最低限、致命的なものを防ぐ、といったイメージです。

pool_kanshiin.png
(これはプール監視のお兄さん)

GASとは?

GASとはGoogle Apps Scriptの略称で、読み方としては「ガス」が多いそうです。(ずっと「ギャス」だと思ってました。ギャス!)
名前の通りGoogleが開発・提供しているプログラミング言語になり、基本的にはJavaScriptをベースに作成されていて書き方はほとんど同じかと思います。

今回はGASで死活監視を行いましたが、他にも方法はたくさんありますのであくまで一例として参考にしていただければと思います。

よし、じゃあ早速コードを書くぞ!!

、、といきなり手をつけてもコードはかけないので、まずは今わかっていないことを整理しよう

①どのようにサイトが死んでいるかどうかの判断をするのか
②Slackへの通知の方法

大きくですが、この①②がわかれば、手を動かすイメージが付きそう!
ということで、1つずつ調べていきました。

①どのようにサイトが死んでいるかどうかの判断をするのか

サイト上の一部の文字が取得できるかどうかとか。。?
サイトが見れない時のエラー文が含まれているかどうかとか・・?

kangaeruhito.png

と、あれやこれや考えながら死活監視を調べてみましたが、
どうやらHTTPレスポンスステータスコードというものがあるそうです。
画面のこういうやつです。404の部分です。
スクリーンショット 2021-06-20 19.08.49.png
聞いたことはありましたし、こういう時に使えるものなんだなと理解しました。

HTTPレスポンスステータスコードとは

超ざっくりですが、HTTPリクエストが正常に完了したかどうかを示すコードです。
ざっと、コード別に分けるとこんな感じです。

・情報レスポンス (100–199)
・成功レスポンス (200–299)
・リダイレクト (300–399)
・クライアントエラー (400–499)
・サーバエラー (500–599)

今回はこのステータスコードが200ならOK、200以外ならNGとして通知をさせることにしました。

これで①は何とかなりそう!

②Slackへの通知の方法

なぜSlackかという部分は、普段社内の連絡ツールとしてSlackを使っているためです。
Slackに通知が来れば、例えばメールよりもすぐに気づいて対応できるだろうと。

Slack×GASの書き方は大量に記事があったので助かりました。
先人の皆様、ありがとうございます。。
参考リンクは最後にまとめて掲載させていただきます。

GASにはSlackライブラリというものがあり、ライブラリを設定?し、
トークンを取得すればAPI認証等が不要で簡単にSlackへの投稿ができるとのことでした。

②もライブラリのおかげでイメージもついた!

ということで、やっとこさコードを書きます。

Slackのトークンの取得や通知方法は、ほとんどこちらの記事を見て
設定させていただいたので、省略させていただきます。

実際に書いたコード

//SlackAPIで登録したボットのトークンを設定する
const token = PropertiesService.getScriptProperties().getProperty('SLACK_API_TOKEN');
//ライブラリから導入したSlackAppを定義し、トークンを設定する
const slackApp = SlackApp.create(token);
//Slackボットがメッセージを投稿するチャンネルを定義する
const channelId = PropertiesService.getScriptProperties().getProperty('SLACK_CHANNELID');
// siteURLを定義
const siteUrl = PropertiesService.getScriptProperties().getProperty('SITE_URL');


function isSiteAlive() {
  const response = UrlFetchApp.fetch(siteUrl, { muteHttpExceptions:true });
  // レスポンスコードを取得
  const code = response.getResponseCode();
  // レスポンスコードが200かどうかでメッセージを変更
    if(code == 200 ) {
      const message = 'サイトは問題なく作動しています';
        slackApp.postMessage(channelId, message);
    else{
      const message = '<!channel> サイトがダウンしています!至急確認してください!!';
      slackApp.postMessage(channelId, message);
    }
};

ここで分かりにくかった部分だけ補足で解説です。

const response = UrlFetchApp.fetch(siteUrl, { muteHttpExceptions:true });

ここでの

UrlFetchApp

はHTTPリクエストを行うためのクラスになります。

そして
muteHttpExceptions:true

こちらはUrlFetchApp.fetch() メソッドと一緒に使用し、
trueに指定しておくと(デフォルトはfalse)エラーを吐かずにHttpResponse を返してくれるようになります。
つまり、HttpResponse の中身を見ればどんなエラーなのかが分かるということです。
今回は返ってくるレスポンスコードを元にSlackに通知を送りたいのでtrueとしています。

あとは最初に並んでいる変数のような部分
//SlackAPIで登録したボットのトークンを設定する
const token = PropertiesService.getScriptProperties().getProperty('SLACK_API_TOKEN');
//ライブラリから導入したSlackAppを定義し、トークンを設定する
const slackApp = SlackApp.create(token);
//Slackボットがメッセージを投稿するチャンネルを定義する
const channelId = PropertiesService.getScriptProperties().getProperty('SLACK_CHANNELID');
// siteURLを定義
const siteUrl = PropertiesService.getScriptProperties().getProperty('SITE_URL');

こちらはプロパティに値を設定することで、コードにベタ書きをせずにすみます。
(プロパティの設定方法が、以前のエディタのフォーマットでしかできなかったので
その時だけエディタの以前のバージョンに戻していました。。)

スクリーンショット 2021-06-20 18.35.50.png

もし新しいエディタでの方法があれば教えていただきたいです!

エディタ上で実行し、大丈夫そうであればトリガーを設定します。
以下の画面から、今回は1分置きの設定にしました。
スクリーンショット 2021-06-20 18.38.17.png

結果、、、
スクリーンショット 2021-06-20 19.04.18.png

無事通知が来るようになりました(パチパチ)

最後に(今回の課題)

今回のコードだと以下の課題があります。
1つのサイトのみの監視しかできない
サイトがダウンしている場合、復旧するまでずっと全員にメンションで通知が続く(うるさい)

これを
複数のサイトの監視
サイトが落ちた時に通知が来て、次に復旧するまでは通知が来ないようにする
という部分が次の課題かと思います。
ここの課題についてはまた次の記事で書ければと思います!

参考リンク

https://e-words.jp/w/死活監視.html
https://developer.mozilla.org/ja/docs/Web/HTTP/Status
https://auto-worker.com/blog/?p=2904
https://tonari-it.com/gas-web-api-http-urlfetch/

Discussion