MENU

AWS LambdaでWebサイトの死活監視を行う

  • URLをコピーしました!

こんにちは、みーまです。

業務で「Webサービスの死活監視をしたい」というリクエストを受け、Pythonでコードを書きましたので残しておきます。

「CloudWatch Syntheticsでもいいじゃない」みたいな話はあるんですが、技術として枯れていてシンプルなので。

目次

HTTPステータスコードが期待と異なる場合Slack通知

動作

  • 指定したサイトに対してGETリクエストを行う
  • HTTPステータスコードを取得し、期待値と異なる場合Slackに通知
  • DNSダウンなど、何らかの理由でGETリクエストが失敗した場合も内容を変えてSlackに通知

環境変数

実行のために環境変数を使います。

項目用途(参考値)
environment環境認識文字列(production/staging)
healthcheck_urlチェック対象のURL('https://aws.amazon.com/jp/)
healthcheck_code期待するHTTPステータスコード

コード

  • slack_pathおよびpost_channelは適宜書き替えてください。
  • os.getenv()にデフォルト値を渡しているので、最終行を有効化すれば単体テストもできます。
import requests
import json
import os


def lambda_handler(event, context):
    environment = os.getenv('environment', 'test')
    healthcheck_url = os.getenv(
        'healthcheck_url', 'https://aws.amazon.com/jp/')
    healthcheck_code = int(os.getenv('healthcheck_code', 418))  # strで格納の為キャスト
    slack_path = "/services/***********/***********/**********************"
    title = f"{environment.title()}サイトダウン検知"

    # access to website
    try:
        r = requests.get(healthcheck_url)
    except requests.exceptions.RequestException as e:
        message = "以下のサイトに通信が到達しません。状況を確認してください。\n"
        message += f"URL: {healthcheck_url}\n"
        message += f"STATUS: FAILED({e})"
        print(f"STATUS: FAILED({e})")
        post_to_slack(title, message, slack_path)
    else:
        message = "以下のサイトが期待されるステータスコードを返しません。状況を確認してください。\n"
        message += f"URL: {healthcheck_url}\n"
        message += f"STATUS: UNMATCH({r.status_code})"
        # check status_code
        if r.status_code != healthcheck_code:
            post_to_slack(title, message, slack_path)
            # print log
            print(
                f"STATUS: UNMATCH({r.status_code})")
        else:
            # print log
            print(f"STATUS: SUCCESS({r.status_code})")


# post to slack
def post_to_slack(title, message, path):
    requests.post(
        f"""https://hooks.slack.com{path}""",
        data=json.dumps({
            "channel": "#post_channel",
            "attachments": [{
                "color": "#FF0000",
                "title": f"{title}",
                "text": f"{message}",
            }],
            "icon_emoji": ":aws:",
        }),
        headers={'Content-Type': 'application/json'}
    )


# for local test
# lambda_handler("event", "context")

実際どう使っているのか

  • CloudWatch Eventsで5分おきのcronイベントを作り、Lambdaを呼び出しています。
  • 今のところサイトがダウンしたことがないので、まだ活躍してません。
  • フロントエンドがECS on Fargateなので、当分活躍することもないかなと思ってます。

以上です。

目次