【GAS】Webページの死活を監視しSlack通知する【定期実行】

こんにちは。

最近当サイト「パン工房」のサーバーの調子がどうも悪いです。いつの間にか接続ができなくなっており、ユーザーの皆さんに対して損失を与えてしまっています。そこで、GASの定期実行を使って死活監視をすることにしました。定期的にWebページの状態を監視し、問題があればSlackに通知するGASを紹介します。

サーバーが不安定

このサイトはVPSで運用していますが、最近サイトにアクセスできない事象が頻発しました。事象は大きく2つに分けられます。

  • Next.jsで例外が発生し500エラーになる
  • サーバー自体が応答しなくなる

1つ目に関しては、サイトの更新作業中にアクセスがあった際にNext.jsでエラーが発生してしまい、HTTPステータスコード500を返してしまうという状態です。ページ数が多くNext.jsのビルドには1分半ほどかかってしまうのですが、稀にビルド自体が進まなくなってしまったり、ビルド中のアクセスで更新前後の整合性が取れなくなってしまったのか500エラーから復旧できなくなったりします。ここについては、ダウンタイム無しでサイトを更新する方法を模索中です。

2つ目は突然起きたので正直原因は分かっていませんが、サーバーが応答しなくなるということが起きました。コンソールで様子を見ようと思いましたがSSH接続もできない状態になってしまっていたため、利用しているConoHa VPSの管理画面からサーバーを再起動して解決しました。このときはアクセスしてもずっと読み込み中でタイムアウトしてしまう状態だったので、ユーザーを困惑させてしまったと思います。恐らくメモリを食いつぶしてしまったのかなと推測していますが、Next.jsの使い方が悪いのか、WORKSページにも結構手の込んだページがあるためメモリリークでも起こしているのかもしれません。

とりあえず死活監視

デプロイ方法の見直しとサーバー落ちの原因究明をしなければならないのですが、とはいえ何も起きていなければ普通にアクセスができる状態です。前回アクセスできなくなったときはそれに気づいておらず2時間ほど繋がらない状態になってしまいました。アクセスできないことに気づければ対処は可能であるため、まずはサーバーがきちんと動いているか、サーバーエラーを起こしていないかを定期的に監視し、問題がある場合にSlackに通知する仕組み(いわゆる死活監視)を作ろうと思いました。

死活監視GASプログラム

というわけでGASを使った死活監視スクリプトがこちらです。

function sendToSlack(message) {
  const url = 'https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXX'
  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify({
      username: '監視bot',
      icon_emoji: ':sob:',
      text: `<@XXXXXXXXX> \n
${message}
サーバーの状況を確認してください。
`
    })
  }

  UrlFetchApp.fetch(url, options)
}

function main() {
  const url = 'https://example.com'

  const options = {
    muteHttpExceptions: true
  }

  try {
    const response = UrlFetchApp.fetch(url ,options)
    const code = response.getResponseCode()

    if (code !== 200) {
      sendToSlack('サーバーエラーを検知しました。')
    }
  } catch (e) {
    sendToSlack('サーバーからの応答がありません。')
  }
}

作りは非常にシンプルです。UrlFetchAppでサイトのトップページにGETリクエストを送り、サーバーからの応答があるか、サーバーがステータスコード200を返却するかを確認しています。問題があればその内容をSlackのIncoming Webhooksを使って通知するというわけです。

ちなみにURLFetchAppに渡すオプションでmuteHttpExceptionstrueにしていますが、これはデフォルトのfalseの状態だと異常系のステータスコードが返ってきた場合に例外が発生する仕様で、それを防ぐためです。今回はサーバー自体が死んでいる場合とNext.jsがエラーを返している場合を区別したいため、接続できた場合のエラーはレスポンスのステータスコードで、接続できなかった場合はcatchブロックで拾うという形にしています。

監視対象のURLやSlackのIncoming WebhooksのURLは各自用意したものに変更してお使いください。今更ですが2019年頃から新たなIncoming Webhooksの利用にはSlack Appの作成が必須になったため、アプリを持っていない場合はSlack APIのページから作成してください。

あとはGASのトリガーを設定して好きな間隔で自動的に定期実行するだけです。私はとりあえず10分おきに実行しています。これでめでたくサーバーの異常時にSlack通知が来るようになりました。

サーバー異常時のSlack通知
友人と使っているSlackワークスペースで自分宛てにメンション通知するようにしている

というわけで今回は、サーバーの死活監視のためにGASの定期実行を活用する方法でした。とりあえずの対応ですが、大人しく根本原因を探したほうがよさそうです。

それではまた。

関連記事