mozikeru.com

和歌山在住。2児の父。IoTエンジニア。各種ご相談承ります。

Amazon CloudWatch SyntheticでWEBシナリオ監視をローコードで作成する

私が勤務するアットシグナル社では高齢者見守りサービス「絆-ONE」をはじめとする、複数のWEBサービスを運営しています。少人数で複数のWEBサービスを運営するとなると、運用にかかる諸作業の「手軽な自動化」は非常に重要な課題です。

今回はそんな「手軽で強力な自動化」ソリューションの一つ、「本番環境が正常に稼働していることを定期的に、自動で監視出来る仕組みが、標準機能で、手軽に構築できる」しくみについて紹介してみようと思います。

Amazon CloudWatch Synthetic
 
AWSの標準的な監視ソリューションである、CloudWatchの機能の一つで、LambdaでChromeブラAウザHeadlessのWrapperである、Puppeterを自動で構築し、結果に応じてアラートを発報出来るという代物です。
定期的にブラウザからログインして、内容が正しく表示されているかどうかを監視する、、というような仕組みをほぼノーコードで簡単に構築することができます。

以下に簡単に実装の方法を紹介しておきます。
①AWSのコンソールにてCloudWatch→(左サイドメニュー)→アプリケーションのモニタリング内のSynthetics Canariesを選択

f:id:mozikeru:20211017153749p:plain

②Canaryを作成から「設計図を使用する」の「GUIワークフロービルダー」を選択
③Canaryビルーダーに必要項目を入力して作成

という感じです。必要項目については以下です。

 ・名前:任意のタイトルを入力

 ・アプリケーションまたはエンドポイントURL:監視対象WEBサービスのログイン画面URLを入力

で、「ワークフロービルダー」欄の各項目を入力することで実際のスクリプトが作成されていきます。基本は[アクション(何をするか)]、[セレクター(対象はどれか)]の組み合わせで実現できます。
 
【アクション】
クリック、セレクターを確認、テキストを確認、テキストを入力、ナビゲーションでクリックのいずれかを選択。

【セレクター】
DOMのセレクターを入力。[id='xxx']とか[class='xxx']の形式で指定。

【テキスト】
セレクターを確認、テキストを確認、テキストを入力等の項目で使用。入力/確認する文字列を入力。

例えば、よくあるタイプのID/パスワードでのログイン監視であれば、こんな感じです。

f:id:mozikeru:20211017162718p:plain

これで以下の動作が実現できます。
①login_idというidのフォームに「test_user1」と入力
②login_pwというidのフォームに「password」と入力
③loginというclassのボタン要素をクリック
④その後、logoというclassの要素が画面に存在することを確認
(そしてスクリーンショットを取得)

ここまでを入力するだけで、下のnode.jsのソースコードが自動でもりもり生成されていきます。すげー。

var synthetics = require('Synthetics');
const log = require('SyntheticsLogger');
const syntheticsConfiguration = synthetics.getConfiguration();

const flowBuilderBlueprint = async function () {
    // INSERT URL here
    let url = "";

    // Get synthetics configuration
    let syntheticsConfig = synthetics.getConfiguration();

    // Set configuration values
    syntheticsConfig.setConfig({
       screenshotOnStepStart : true,
       screenshotOnStepSuccess: true,
       screenshotOnStepFailure: true
    });

    syntheticsConfiguration.setConfig({
        includeRequestHeaders: true, // Enable if headers should be displayed in HAR
        includeResponseHeaders: true, // Enable if headers should be displayed in HAR
        restrictedHeaders: , // Value of these headers will be redacted from logs and reports
        restrictedUrlParameters: [] // Values of these url parameters will be redacted from logs and reports
    });
    let page = await synthetics.getPage();

    // Navigate to the initial url
    await synthetics.executeStep('navigateToUrl', async function (timeoutInMillis = 30000) {
        await page.goto(url, {waitUntil: ['load', 'networkidle0'], timeout: timeoutInMillis});
    });

    // Execute customer steps
    await synthetics.executeStep('input', async function () {
        await page.type("[id='login_id']", "test_user1");
    });
    await synthetics.executeStep('verifyText', async function () {
        await page.waitForXPath("//[id=\'login_pw\'][contains(text(),'password')]", { timeout: 30000 });
    });
    await synthetics.executeStep('click', async function () {
        await page.waitForSelector("[class='login']", { timeout: 30000 });
        await page.click("[class='login']");
    });
    await synthetics.executeStep('verifyText', async function () {
        await page.waitForXPath("//[class=\'logo\'][contains(text(),'')]", { timeout: 30000 });
    });

    
};

exports.handler = async () => {
    return await flowBuilderBlueprint();
};

成果物はソースコードなので、timeoutの値を編集して長くしたりといったカスタマイズが可能。

定期実行も設定一発。

f:id:mozikeru:20211017164145p:plain


通知の条件を設定。
また、作成した監視はCloudWatchのトリガーとして扱えるので、既存の通知と連携できます(仕組みを作っておけばSlackやchatworkに通知する等)。

f:id:mozikeru:20211018090750p:plain

 

とても便利なのでWEBサービスを運用しているのであればとりあえず実装しておくのが吉かと思います。