Azure
AzureFunctions

Azure FunctionでWebAPIを定期的に監視し異常をSlackに通知

Azure Functionにある指定時間に処理を実行する機能「Timer Triger」を利用して、WebAPIに繋がるか/正常な値を返すか一定時間間隔でチェックを行い、異常があればSLACKに通知を行う。

Timer Trigerは現段階ではC#、F#、JavaScriptしか対応していないようなため、今回はJavaScriptで行う。

通知先のSLACKのWeb Hook URL取得

  1. slack画面左下の「App」の+ボタンをクリック

image.png

  1. 「incomming-webhook」で検索し「インストール」をクリック

image.png

  1. Webhook URLをコピーしておく

webhook.png

Azure Functionの設定

  1. ポータルサイトの左メニューの「App Service」→「+追加」→「Function App」→「作成」

image.png

  1. ポータルサイトの左メニューの「Function App」→「関数」→「新しい機能」

azure_function2.png

  1. 「Timer Triger」を選択 → 言語(JavaScript)指定 → 実行する時間指定 → 作成

azure_function4.png

Scheduleに実行日時を入力。
6時間毎に0分0秒に実行の場合、「0 0 */6 * * *」と入力。

requestモジュールのインストール

初期状態ではrequestモジュールが使用できないのでインストールする。

https://[function-name].scm.azurewebsites.net/DebugConsole
からデバッグコンソールを開きます。([function-name]に自分のファンクションApp名を入力)

cdでD:\home\site\wwwroot[関数名]へ移る。

D:\home>cd site\wwwroot\TimerTriggerJS1
D:\home\site\wwwroot\TimerTriggerJS1> 

requestモジュールのインストール

D:\home\site\wwwroot\TimerTriggerJS1>npm init
D:\home\site\wwwroot\TimerTriggerJS1>npm install --save request

テスト実行と保存

以下を入力して「保存および実行」を押すとテスト実行される。
動作に問題なければ「保存」を押すことでScheduleで指定した時間で実行される。

module.exports = function (context, myTimer) {
    var SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/〇/△/□"; // ↑でコピーした通知先SLACKのWebhook URL
    var API_URL = "http://〇.〇.〇.〇/api/hoge"; // 死活チェックするWebAPIのURL

    var data = "";
    var channel = "channel_name"; // 通知先のSLACKチャンネル名

    var request = require('request');
    var http = require('http');


    var options = {
        url: API_URL
        ,method: 'GET'
        ,json: true
    };

    var payload = {};
    payload.username = "hoge_bot"; //slackに表示される名前
    payload.icon_emoji = ":anger:" // アイコン
    payload.channel = channel;


    http.get(API_URL, (res) => {
        const { statusCode } = res;
        const contentType = res.headers['content-type'];

        context.log(statusCode);
        let error;
        if (statusCode !== 200) {
            data = "Failure accessing " + API_URL + ", Status Code : " + statusCode;
        } else if (!/^application\/json/.test(contentType)) {
            error = new Error('Invalid content-type.\n' +
                            `Expected application/json but received ${contentType}`);
        }
        if (error) {
            data = "API_URLにアクセスに失敗した。" + ", " + String(error);
        }

        res.setEncoding('utf8');
        let rawData = '';
        res.on('data', (chunk) => { rawData += chunk; });
        res.on('end', () => {
            try {
                const parsedData = JSON.parse(rawData);
                if ("<返されるJSONデータに含まれるキー>" in parsedData) {
                    articles = parsedData.articles;
                } else {
                    data = "パースした結果にキーが含まれていなかった。" + String(rawData);
                }

            } catch (e) {
                context.error(e.message);
                data = "パース自体に失敗した" + String(rawData);
            }

            payload.text = data;

            var options = {
                url: SLACK_WEBHOOK_URL
                ,method: 'POST'
                ,headers: 'Content-type: application/json'
                ,json: payload
            };
            request.post(options, function (error, response, body) {
                context.log("Response Code : "+response.statusCode);
            })
            context.done();
        });

    }).on('error', (e) => {
        data = API_URL + "へアクセスできませんでした。ERROR : " + + String(e);

        payload.text = data;

        var options = {
            url: SLACK_WEBHOOK_URL
            ,method: 'POST'
            ,headers: 'Content-type: application/json'
            ,json: payload
        };
        request.post(options, function (error, response, body) {
            context.log("Response Code : "+response.statusCode);
        })
        context.done();
    });

};

image.png

動作

image.png

料金

6時間に1回実行で0.32円/1日≒10円/30日程度

azure_function3.png