Closed8

AutoWebPerf を使ってみる

Wataru TaguchiWataru Taguchi

アーキテクチャ

コネクタからテストのリストを取得し、ギャザラーを介してパフォーマンスを取得し、コネクタに結果を出力する

  • the engine
  • connector modules
    • スプレッドシート
    • JSON
    • CSV
  • gatherer modules
    • CrUX API
    • CrUX BigQuery
    • PageSpeed Insights API
    • WebPageTest API
Wataru TaguchiWataru Taguchi

クイックスタート

git clone https://github.com/GoogleChromeLabs/AutoWebPerf.git
cd AutoWebPerf
npm i
./awp run examples/tests.json output/results.json
examples/tests.json
{
  "tests": [
    {
      "label": "web.dev",
      "url": "https://web.dev",
      "gatherer": "psi"
    }
  ]
}

結果は下記

output/results.json
{
  "results": [
    {
      "id": "1610180070705-https://web.dev",
      "type": "Single",
      "gatherer": "psi",
      "status": "Retrieved",
      "label": "web.dev",
      "createdTimestamp": 1610180070705,
      "modifiedTimestamp": 1610180070705,
      "errors": [],
      "url": "https://web.dev",
      "psi": {
        "status": "Retrieved",
        "statusText": "Success",
        "settings": {},
        "metadata": {
          "testId": "https://web.dev/",
          "requestedUrl": "https://web.dev/",
          "finalUrl": "https://web.dev/",
          "lighthouseVersion": "6.3.0",
          "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/85.0.4183.140 Safari/537.36",
          "fetchTime": "2021-01-09T08:14:31.866Z"
        },
        "metrics": {
          "RenderBlockingResources": 0,
          "crux": {
            "LargestContentfulPaint": {
              "category": "FAST",
              "percentile": 2475,
              "good": 0.761798544259217,
              "ni": 0.15437896219769925,
              "poor": 0.08382249354308509
            },
            "FirstInputDelay": {
              "category": "FAST",
              "percentile": 17,
              "good": 0.9399224806201529,
              "ni": 0.04069767441860455,
              "poor": 0.01937984496124033
            },
            "FirstContentfulPaint": {
              "category": "AVERAGE",
              "percentile": 2521,
              "good": 0.18828643331045844,
              "ni": 0.6437886067261603,
              "poor": 0.16792495996339965
            },
            "CumulativeLayoutShift": {
              "category": "FAST",
              "percentile": 3,
              "good": 0.7931119920713579,
              "ni": 0.07210109018830525,
              "poor": 0.13478691774033683
            }
          },
          "lighthouse": {
            "FirstContentfulPaint": 1411,
            "FirstMeaningfulPaint": 1682,
            "LargestContentfulPaint": 3318.111530962102,
            "SpeedIndex": 2162,
            "TimeToInteractive": 5448,
            "FirstCPUIdle": 4085,
            "FirstInputDelay": 13,
            "TotalBlockingTime": 109,
            "CumulativeLayoutShift": 0,
            "TotalSize": 392,
            "HTML": 7,
            "Javascript": 140,
            "CSS": 25,
            "Fonts": 74,
            "Images": 135,
            "Medias": 0,
            "ThirdParty": 202,
            "UnusedCSS": 21,
            "WebPImages": 0,
            "OptimizedImages": 0,
            "ResponsiveImages": 0,
            "OffscreenImages": 0,
            "DOMElements": 307,
            "Performance": 0.88,
            "ProgressiveWebApp": 1,
            "Manifest": 1,
            "ServiceWorker": 1,
            "Offline": 1,
            "Accessibility": 1,
            "SEO": 0.99,
            "BestPractices": 1
          }
        },
        "errors": []
      }
    }
  ]
}
Wataru TaguchiWataru Taguchi

定期的なテスト

準備

./awp recurring examples/tests-recurring.json output/results.json
examples/tests-recurring.json
{
  "tests": [
    {
      "label": "web.dev",
      "url": "https://web.dev",
      "recurring": {
        "frequency": "Daily",
        "nextTriggerTimestamp": 1606955174906
      },
      "gatherer": "psi",
      "errors": []
    }
  ]
}

実行すると tests.recurring.nextTriggerTimestamp が現在時刻 + 1 日に更新される

これは tests.recurring.frequencyDaily に設定されているため、次の実行日時をテスト実行時の + 1日に更新したのだと思われる

↓実行後

examples/tests-recurring.json
{
  "tests": [
    {
      "label": "web.dev",
      "url": "https://web.dev",
      "recurring": {
        "frequency": "Daily",
        "nextTriggerTimestamp": 1610267063035
      },
      "gatherer": "psi",
      "errors": []
    }
  ]
}

更新後もう一度同じコマンドを実行しても、テストは実行されない

これはたぶん現在時刻が tests.recurring.nextTriggerTimestamp より前の日だからだと思われる

実行

準備はつまるところ、tests.recurring.nextTriggerTimestamp を更新しているので手動で書き換えても良い

./awp continue examples/tests-recurring.json output/results.json

tests.recurring.nextTriggerTimestamp を1分後などにして動作テストしていたのだが実行されなかった

理由は、どうやら 10 分毎に実行するかチェックをしているっぽいので、動作テストをする場合は10分待つ必要がある

async continue(options) {
  options = options || {};
  options.recurring = true;
  let self = this;
  let isRunning = false;

  // Set timer interval as every 10 mins by default.
  let timerInterval = options.timerInterval ? 
      parseInt(options.timerInterval) : 60 * 10;

  if (options.verbose) {
    this.log(`Timer interval sets as ${timerInterval} seconds.`);
  }

  await self.recurring(options);

  // Run contiuously.
  return await new Promise(resolve => {
    const interval = setInterval(async () => {
      if (isRunning) return;

      await self.recurring(options);
      await self.retrieve(options);
      isRunning = false;

      if (options.verbose) {
        self.log('Waiting for next timer triggered...');
      }
    }, timerInterval * 1000);
  });
}

無事10分待って定期的な実行を確認 👍

Wataru TaguchiWataru Taguchi

スプレッドシートへの書き込み

https://github.com/GoogleChromeLabs/AutoWebPerf/blob/stable/docs/sheets-connector.md

手順1 サービスアカウントの作成

すでにサービスアカウントがある場合はスキップ

https://cloud.google.com/iam/docs/creating-managing-service-accounts

編集者権限が必要なので、作成時につける

Google Sheets API を有効化しておく

手順2 スプレッドシートの作成

公式からサンプルが提供されているのでこれを参考に作成する
https://docs.google.com/spreadsheets/d/1c3k9eEVg12Atoa72tglVVBg--o0CEMkOF3JCaLlxzeo/edit#gid=0

Tests タブと、Results タブを作成

Resuts は空で、Tests にはせっかくなので自分が運営しているサイトと、比較のために web.dev を指定

シートを先程作ったサービスアカウントに共有する


手順3 service-account.json の作成

サービスアカウントの詳細画面の「鍵を追加」から作る

AutoWebPerf では tmp.gitignore に追加されているので、tmp ディレクトリ配下に置いておく

手順4 Chrome UX Report API キーの作成

Chrome UX Report API を有効化しておく

キーはデフォルトで作られる

手順5 実行

https://docs.google.com/spreadsheets/d/1c3k9eEVg12Atoa72tglVVBg--o0CEMkOF3JCaLlxzeo/edit

MY GOOGLE SHEET ID は↑の URL であれば 1c3k9eEVg12Atoa72tglVVBg--o0CEMkOF3JCaLlxzeo になる

SERVICE_ACCOUNT_CREDENTIALS=./tmp/service-account.json CRUX_APIKEY=MY_API_KEY ./awp run sheets:[MY GOOGLE SHEET ID]/Tests sheets:[MY GOOGLE SHEET ID]/Results

成功したが、自分のサイトはデータがなかった(悲しい)

Wataru TaguchiWataru Taguchi

DataStudio での可視化

https://github.com/GoogleChromeLabs/AutoWebPerf/blob/stable/docs/sheets-connector.md

CrUX API

テンプレートが用意されているのでこちらを元に作っていきます

https://datastudio.google.com/reporting/5f7b6c8c-cae2-4cf2-97a4-06af250a0039/page/X6nFB/preview

「テンプレートを使用」をクリックし、「新しいデータソース」→「新しいデータソースの作成」

先程作ったスプレッドシートの Results を選択します

「レポートに追加」

「レポートをコピー」で作成します

良い感じにグラフが表示されました!

Wataru TaguchiWataru Taguchi

Firebase Functions で定期実行

https://firebase.google.com/docs/functions/schedule-functions?hl=ja

課金は必須ですが、Cloud Scheduler の各ジョブのコストは月額 $0.10(USD)であり、Google アカウントごとに 3 つのジョブを無料で使用できるため、全体的なコストは管理可能であることが期待できます

3つまでは無料とのこと

実装

https://github.com/GoogleChromeLabs/AutoWebPerf#usage-of-autowebperf-core

コード上で利用する場合 README とは引数が少し違う

tests, results はコマンドラインからの実行と同じように connectorpath を定義する

環境変数は envVars 経由で渡す必要がある

SERVICE_ACCOUNT_CREDENTIALS の取得に少し工夫しています

functions/src/awp.ts
import * as admin from "firebase-admin";
const AutoWebPerf = require('awp/src/awp-core');

admin.initializeApp();
const bucket = admin.storage().bucket();

const SHEET_ID = 'XXX';
const SERVICE_ACCOUNT_CREDENTIALS_FILE_NAME = 'service-account.json';
const LOCAL_SERVICE_ACCOUNT_CREDENTIALS_PATH = `/tmp/${SERVICE_ACCOUNT_CREDENTIALS_FILE_NAME}`;
const SERVICE_ACCOUNT_CREDENTIALS_PATH = `..${LOCAL_SERVICE_ACCOUNT_CREDENTIALS_PATH}`;
const CRUX_APIKEY = 'XXX';

export async function run() {
  await bucket.file(SERVICE_ACCOUNT_CREDENTIALS_FILE_NAME).download({
    destination: LOCAL_SERVICE_ACCOUNT_CREDENTIALS_PATH
  });

  const awp = new AutoWebPerf({
    "tests": {
      "connector": "sheets",
      "path": `${SHEET_ID}/Tests`
    },
    "results": {
      "connector": "sheets",
      "path": `${SHEET_ID}/Results`
    },
    "envVars": {
      "SERVICE_ACCOUNT_CREDENTIALS": SERVICE_ACCOUNT_CREDENTIALS_PATH,
      "CRUX_APIKEY": CRUX_APIKEY
    }
  });
  awp.run();
}

functions/src/index.ts
import * as functions from 'firebase-functions';
import { run } from './awp';

export const scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(() => {
  run();
  return null;
});

デプロイ

最初ロケーションを設定していなかったのでビルド時にエラーになった

Error: Cloud resource location is not set for this project but scheduled functions requires it. Please see this documentation for more details: https://firebase.google.com/docs/projects/locations.

https://firebase.google.com/docs/functions/schedule-functions?hl=ja#before_you_begin

このスクラップは2021/01/14にクローズされました