チュートリアル: Evidently のサンプルアプリケーションを使用した A/B テスト - Amazon CloudWatch

チュートリアル: Evidently のサンプルアプリケーションを使用した A/B テスト

このセクションでは、A/B テストに Amazon CloudWatch Evidently を使用するチュートリアルを提供します。このチュートリアルでは、シンプルな React アプリケーションである Evidently のサンプルアプリケーションを使用します。サンプルアプリケーションで、showDiscount 機能を表示するかどうかを設定します。ユーザーがこの機能を表示すると、ショッピングサイトで表示される価格が 20% の割引価格で表示されます。

このチュートリアルでは、一部のユーザーに割引を表示して他のユーザーには表示しなくすることに加え、両方のバリエーションからページのロード時間のメトリクスを収集するように Evidently を設定します。

ステップ 1: サンプル アプリケーションのダウンロード

まず、Evidently のサンプルアプリケーションをダウンロードします。

サンプルアプリケーションをダウンロードするには
  1. 次の Amazon S3 バケットから、サンプルアプリケーションをダウンロードします。

    https://evidently-sample-application.s3.us-west-2.amazonaws.com/evidently-sample-shopping-app.zip
  2. パッケージを解凍します。

ステップ 2: Evidently エンドポイントの追加と認証情報の設定

次に、以下の例のように、サンプルアプリケーションのパッケージの src ディレクトリにある config.js ファイルに、Evidently の リージョンとエンドポイントを追加します。

evidently: { REGION: "us-west-2", ENDPOINT: "https://evidently.us-west-2.amazonaws.com (https://evidently.us-west-2.amazonaws.com/)", },

また、アプリケーションに CloudWatch を呼び出すためのアクセス許可があることを確認する必要があります。

サンプルアプリケーションに Evidently を呼び出すためのアクセス許可を付与するには
  1. AWS アカウントにフェデレートします。

  2. IAM ユーザーを作成し、AmazonCloudWatchEvidentlyFullAccess ポリシーをそのユーザーにアタッチします。

  3. 次のステップで必要になるため、IAM ユーザーのアクセスキー ID とシークレットアクセスキーを書きとめておきます。

  4. 次の例のように、このセクションの前半で変更したものと同じ config.js ファイルに、アクセスキー ID とシークレットアクセスキーの値を入力します。

    credential: { accessKeyId: "Access key ID", secretAccessKey: "Secret key" }
    重要

    このステップを使用すると、サンプルアプリケーションを可能な限り簡単に試すことができます。実際の本番アプリケーションに IAM ユーザーの認証情報を組み込むことはお勧めしません。代わりに、Amazon Cognito を認証に使用することをお勧めします。詳細については、「Amazon Cognito のウェブアプリケーションとモバイルアプリケーションとの統合」を参照してください。

ステップ 3: 機能評価用のコードをセットアップする

CloudWatch Evidently を使用して機能を評価する場合は、[EvaluateFeature] オペレーションを使用して、ユーザーセッションごとに機能のバリエーションをランダムに選択する必要があります。このオペレーションは、実験で指定した割合に従って、機能の各バリエーションにユーザーセッションを割り当てます。

ブックストアデモアプリケーションの機能評価コードをセットアップするには
  1. サンプルアプリケーションが Evidently を呼び出せるようにするために、src/App.jsx ファイルにクライアントビルダーを追加します。

    import Evidently from 'aws-sdk/clients/evidently'; import config from './config'; const defaultClientBuilder = ( endpoint, region, ) => { const credentials = { accessKeyId: config.credential.accessKeyId, secretAccessKey: config.credential.secretAccessKey } return new Evidently({ endpoint, region, credentials, }); };
  2. const App コードセクションに以下を追加して、クライアントを起動します。

    if (client == null) { client = defaultClientBuilder( config.evidently.ENDPOINT, config.evidently.REGION, );
  3. 次のコードを追加して、evaluateFeatureRequest を作成します。このコードで、チュートリアルの後半で推奨するプロジェクト名と機能名を事前に入力しておきます。Evidently コンソールでプロジェクト名と機能名を指定すれば、独自のプロジェクト名と機能名に置き換えることができます。

    const evaluateFeatureRequest = { entityId: id, // Input Your feature name feature: 'showDiscount', // Input Your project name' project: 'EvidentlySampleApp', };
  4. 機能評価のために Evidently を呼び出すコードを追加します。リクエストが送信されると、Evidently は showDiscount 機能を表示するかどうかを指定するためにユーザーセッションをランダムに割り当てます。

    client.evaluateFeature(evaluateFeatureRequest).promise().then(res => { if(res.value?.boolValue !== undefined) { setShowDiscount(res.value.boolValue); } getPageLoadTime() })

ステップ 4: 実験メトリクスのコードのセットアップ

カスタムメトリクスの場合は、Evidently のPutProjectEvents API を使用してメトリクスの結果を Evidently に送信します。次の例では、カスタムメトリクスを設定し、実験データを Evidently に送信する方法を示しています。

以下の関数を追加してページのロード時間を計算し、PutProjectEvents を使用してメトリクスの値を Evidently に送信します。次の機能を Home.tsx に追加し、EvaluateFeature API でこの関数を呼び出します。

const getPageLoadTime = () => { const timeSpent = (new Date().getTime() - startTime.getTime()) * 1.000001; const pageLoadTimeData = `{ "details": { "pageLoadTime": ${timeSpent} }, "UserDetails": { "userId": "${id}", "sessionId": "${id}"} }`; const putProjectEventsRequest = { project: 'EvidentlySampleApp', events: [ { timestamp: new Date(), type: 'aws.evidently.custom', data: JSON.parse(pageLoadTimeData) }, ], }; client.putProjectEvents(putProjectEventsRequest).promise(); }

ダウンロード後、編集した App.js ファイルは次のようになります。

import React, { useEffect, useState } from "react"; import { BrowserRouter as Router, Switch } from "react-router-dom"; import AuthProvider from "contexts/auth"; import CommonProvider from "contexts/common"; import ProductsProvider from "contexts/products"; import CartProvider from "contexts/cart"; import CheckoutProvider from "contexts/checkout"; import RouteWrapper from "layouts/RouteWrapper"; import AuthLayout from "layouts/AuthLayout"; import CommonLayout from "layouts/CommonLayout"; import AuthPage from "pages/auth"; import HomePage from "pages/home"; import CheckoutPage from "pages/checkout"; import "assets/scss/style.scss"; import { Spinner } from 'react-bootstrap'; import Evidently from 'aws-sdk/clients/evidently'; import config from './config'; const defaultClientBuilder = ( endpoint, region, ) => { const credentials = { accessKeyId: config.credential.accessKeyId, secretAccessKey: config.credential.secretAccessKey } return new Evidently({ endpoint, region, credentials, }); }; const App = () => { const [isLoading, setIsLoading] = useState(true); const [startTime, setStartTime] = useState(new Date()); const [showDiscount, setShowDiscount] = useState(false); let client = null; let id = null; useEffect(() => { id = new Date().getTime().toString(); setStartTime(new Date()); if (client == null) { client = defaultClientBuilder( config.evidently.ENDPOINT, config.evidently.REGION, ); } const evaluateFeatureRequest = { entityId: id, // Input Your feature name feature: 'showDiscount', // Input Your project name' project: 'EvidentlySampleApp', }; // Launch client.evaluateFeature(evaluateFeatureRequest).promise().then(res => { if(res.value?.boolValue !== undefined) { setShowDiscount(res.value.boolValue); } }); // Experiment client.evaluateFeature(evaluateFeatureRequest).promise().then(res => { if(res.value?.boolValue !== undefined) { setShowDiscount(res.value.boolValue); } getPageLoadTime() }) setIsLoading(false); },[]); const getPageLoadTime = () => { const timeSpent = (new Date().getTime() - startTime.getTime()) * 1.000001; const pageLoadTimeData = `{ "details": { "pageLoadTime": ${timeSpent} }, "UserDetails": { "userId": "${id}", "sessionId": "${id}"} }`; const putProjectEventsRequest = { project: 'EvidentlySampleApp', events: [ { timestamp: new Date(), type: 'aws.evidently.custom', data: JSON.parse(pageLoadTimeData) }, ], }; client.putProjectEvents(putProjectEventsRequest).promise(); } return ( !isLoading? ( <AuthProvider> <CommonProvider> <ProductsProvider> <CartProvider> <CheckoutProvider> <Router> <Switch> <RouteWrapper path="/" exact component={() => <HomePage showDiscount={showDiscount}/>} layout={CommonLayout} /> <RouteWrapper path="/checkout" component={CheckoutPage} layout={CommonLayout} /> <RouteWrapper path="/auth" component={AuthPage} layout={AuthLayout} /> </Switch> </Router> </CheckoutProvider> </CartProvider> </ProductsProvider> </CommonProvider> </AuthProvider> ) : ( <Spinner animation="border" /> ) ); }; export default App;

ユーザーがサンプルアプリケーションにアクセスするたびに、カスタムメトリクスが Evidently に送信され分析されます。Evidently は各メトリクスを分析し、Evidently ダッシュボードにリアルタイムで結果を表示します。次の例で、メトリクスペイロードを示します。

[ {"timestamp": 1637368646.468, "type": "aws.evidently.custom", "data": "{\"details\":{\"pageLoadTime\":2058.002058},\"userDetails\":{\"userId\":\"1637368644430\",\"sessionId\":\"1637368644430\"}}" } ]

ステップ 5: プロジェクト、機能、実験の作成

次に、CloudWatch Evidently コンソールでプロジェクト、機能、および実験を作成します。

このチュートリアルのプロジェクト、機能、および実験を作成するには
  1. CloudWatch コンソール (https://console.aws.amazon.com/cloudwatch/) を開きます。

  2. ナビゲーションペインで [Application monitoring] (アプリケーションのモニターリング)、[Evidently] を選択します。

  3. [Create project] (プロジェクトを作成) を選択し、フィールドに入力します。サンプルが正しく動作するためには、プロジェクト名に EvidentlySampleApp を使用する必要があります。[Evaluation event storage] (評価イベントストレージ) で、[Don't store Evaluation events] (評価イベントを保存しない) を選択します。

    フィールドに入力したら、[Create profile] (プロファイルを作成) を選択します。

    詳細については、「 の新規プロジェクトの作成」を参照してください。

  4. プロジェクトを作成したら、そのプロジェクトに機能を作成します。機能の名前は「showDiscount」にします。この機能では、Boolean 型のバリエーションを 2 つ作成します。最初のバリエーションの名前を「disable」、値を「False」とし、第 2 のバリエーションの名前を「enable」、値を「True」とします。

    機能の作成の詳細については、「プロジェクトに機能を追加する」を参照してください。

  5. 機能の作成が完了したら、プロジェクト内の実験を作成します。実験の名前は「pageLoadTime」にします。

    この実験では、テスト対象ページのページロード時間を測定する pageLoadTime というカスタムメトリクスを使用します。実験のカスタムメトリクスは、Amazon EventBridge を使用して作成されます。EventBridge の詳細については、「Amazon EventBridge とは」を参照してください。

    そのカスタムメトリクスを作成するには、実験の作成時に次の操作を行います。

    • [Metrics] (メトリクス) の下で、 [Metric source] (メトリクスソース) として [Custom metrics] (カスタムメトリクス) を選択します。

    • [Metric name] (メトリクス名) に、「pageLoadTime」を入力します。

    • [Goal] (目標) には [Decrease] (減少) を選択します。これは、このメトリクスの値が小さいほど機能のバリエーションが最適であることを示します。

    • [Metric rule] (メトリクスルール) では、次のように入力します。

      • エンティティ IDには、UserDetails.userIdと入力します。

      • [Value key] (値キー) には「details.pageLoadTime」と入力します。

      • [Units] (単位) には、「ms」と入力します。

    • [Add metric] (メトリクスを追加) を選択します。

    [Audiences] (対象者) には [100%] を選択し、すべてのユーザーが実験に参加するようにします。バリエーション間のトラフィック分割をそれぞれ 50% に設定します。

    次に、[Create experiment] (実験を作成) を選択して、実験を作成します。作成しても、Evidently に開始するように指示するまで実験は開始されません。

ステップ 6: 実験を開始し、CloudWatch Evidently をテストする

最後のステップでは、実験を開始してサンプルアプリケーションを起動します。

チュートリアルの実験を開始するには
  1. CloudWatch コンソール (https://console.aws.amazon.com/cloudwatch/) を開きます。

  2. ナビゲーションペインで [Application monitoring] (アプリケーションのモニターリング)、[Evidently] を選択します。

  3. [EvidentlySampleApp] プロジェクトを選択します。

  4. [Experiments] (実験) タブを選択します。

  5. [pageLoadTime] の横にあるボタンをクリックし、[Actions] (アクション)、[Start experiment] (実験を開始) を選択します。

  6. 実験が終了する時間を選択します。

  7. [Start experiment] (実験を開始) を選択します。

    実験がすぐに開始されます。

次に、以下のコマンドを使用して Evidently サンプルアプリケーションを起動します。

npm install -f && npm start

アプリケーションが起動すると、テストされる 2 つの機能のバリエーションのうちの 1 つに割り当てられます。1 つのバリエーションでは「20% 割引」と表示されますが、もう一方のバリエーションでは表示されていません。ページの更新を繰り返して、さまざまなバリエーションを表示します。

注記

Evidently にはスティッキーの評価があります。機能の評価は決定論的です。つまり、同じ entityId と機能では、必ず同じバリエーションがユーザーに割り当てられます。時間変動の割り当てが変更されるのは、エンティティがオーバーライドに追加されるか、実験トラフィックがダイヤルアップされる場合のみです。

ただし、サンプルアプリケーションのチュートリアルでの使用を簡単にするために、ページを更新するたびに Evidently によってサンプルアプリケーションの機能の評価が再割り当てされているため、オーバーライドを追加しなくても両方のバリエーションを体験できます。

[Troubleshooting] (トラブルシューティング)

npm バージョン 6.14.14 を使用することをお勧めします。サンプルアプリケーションの構築または起動に関するエラーが表示されており、別のバージョンの npm を使用している場合は、次の手順を実行します。

npm バージョン 6.14.14 をインストールするには
  1. ブラウザを使用して、https://nodejs.org/download/release/v14.17.5/ に接続します。

  2. node-v14.17.5.pkg をダウンロードし、pkg ファイルを開いて npm をインストールします。

    webpack not found エラーが表示された場合は、evidently-sample-shopping-app フォルダを開き、以下のことを試します。

    1. package-lock.json を削除する

    2. yarn-lock.json を削除する

    3. node_modules を削除する

    4. package.json から webpack の依存関係を削除する

    5. 下記を実行します。

      npm install -f && npm