[新機能] フィーチャーフラグやA/Bテストを支援! Amazon CloudWatch Evidentlyがリリースされたので試してみた #reinvent

2021.11.30

CX事業本部、MAD事業部の小倉@大阪オフィスです。

本日、Amazon CloudWatch Evidentlyなる機能がリリースされました。

フィーチャーフラグの管理やA/Bテストの実行を支援する機能になっています。東京リージョンも対応しています。

やってみた

今回はCognitoを使ってログイン処理を行ったユーザに対して、フィーチャーフラグコントロールをやってみることにしました。

Evidently Projectの作成

サイドメニューから「Evidently」を選択し、以下の画面から「Create project」ボタンを押してProjectを作成します。

Project名と説明を入力しました。

「Evalution event storage」の設定を行うと、イベントをS3又はCloudWatch Logsに保存できるようです。私はS3を選択し、バケットの指定を行いました。

Projectが作成されました。

Featureの作成

Projectページの上にある「Add Feature」ボタンを押して、Featureを作成します。

Feature variationsの欄で、機能フラグ、A/Bテストにおいて、AWS側からコントロールしたい値を設定します。

今回は、Reactアプリ上の表示/非表示をAWS側からコントロールしようと思い、以下の様に設定しました。

  • Variation type : Boolean
  • Variation name
    • Variation1 => False
    • Variation2 => True

この値をAWSから取得するとき、True or Falseが返されるようになるイメージです。

Reactアプリの準備

一旦ここでお題となるReactアプリを準備します。下準備として、以下の簡単なアプリを用意しました。

  • create-react-appでReactアプリケーションを作成
  • amplify authを使ってCognitoでユーザ認証可能にする

準備ができたら、amplify publishしてAWSリソースを作成しておきます。

IAMポリシーの準備

作成されたAWSリソースの内、CognitoのAuthRole(認証されたユーザ用のRole)に以下のポリシーを追加します。

  • AmazonCloudWatchEvidentlyFullAccess
  • ResourceGroupsandTagEditorReadOnlyAccess

また、イベント情報をS3/CloudWatch Logsに保存する場合、以下もあわせて追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketPolicy",
                "s3:PutBucketPolicy",
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogDelivery",
                "logs:DeleteLogDelivery",
                "logs:DescribeResourcePolicies",
                "logs:PutResourcePolicy"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Evidently-permissions.html

Reactアプリの編集

AWS側で管理する値を取得、参照するように、以下のコードを作成しました。フラグによって、「Learn React」部分の表示/非表示を切り替えます。

尚、aws-sdk-jsは今朝(2021/11/30)リリースされたv2.10.39.0でAmazon CloudWatch Evidentlyに対応しています。

import logo from './logo.svg';
import './App.css';
import Amplify from "aws-amplify";
import awsExports from "./aws-exports";
import {withAuthenticator} from '@aws-amplify/ui-react'
import Evidently from "aws-sdk/clients/evidently";
import {Auth} from "@aws-amplify/auth";
import {useEffect, useState} from "react";

Amplify.configure(awsExports);

async function getEvaluateFeature(){

    const credentials  = await Auth.currentCredentials();
    const userinfo  = await Auth.currentUserInfo();
    console.log(userinfo)

    // Initialize the Amazon CloudWatch Evidently client
    const evidently = new Evidently({
        endpoint: 'https://evidently.ap-northeast-1.amazonaws.com',
        credentials: credentials,
        region: 'ap-northeast-1'
    });

    // API request structure
    const evaluateFeatureRequest = {
        // entityId for calling evaluate feature API
        entityId: userinfo.username,
        // Name of your feature
        feature: 'example-feature-1',
        // Name of your project
        project: "Evidently-Test-Project",
    };

    return evidently.evaluateFeature(evaluateFeatureRequest).promise();
}

function App() {

    const [variation, setVariation] = useState();

    useEffect(() => {
        (async() =>{
         const res = await getEvaluateFeature();
         console.log(res)
         console.log(res.value)
         setVariation(res.value.boolValue)
        })()
    },[])


  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
          { variation &&
          <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
          >
              Learn React
          </a>
          }
      </header>
    </div>
  );
}

export default withAuthenticator(App)
  • 認証されたユーザのクレデンシャル、ユーザ情報を取得
  • Amazon CloudWatch Evidentlyのクライアントを初期化
  • entityId,feature名、project名を指定してフラグ値取得リクエスト

entityIdは、ユーザをセグメント化する文字列を指定します。今回はCognitoのユーザ名にしました。

この状態でアプリを起動してみると、フラグの値はFeature画面でデフォルトに指定したFalseが常に返ってくるようになっています。

Launchの設定

フラグ管理したい機能をローンチします。Projectページの上にある「Create launch」から設定します。

Feature nameの欄で、事前に作成したexample-feature-1を指定します。

Launch configurationでは、「Start launch now」で直ちに設定が反映されるようにします。

(Schedule launchを選択すると、日時指定での設定が可能です)

先ず、必ずFalseの値が返る様に、Variation1を100%に設定してみます。

アプリにアクセスすると、取得したフラグの値がFalseであり、「Learn React」が非表示になっています。

次に、必ずTrueとなるよう、Variation2を100%に変更してみます。

今度はTrueが取得出来、「Learn React」が表示されるようになりました。

今度はTrue,Falseの割合をそれぞれ50%にしてみます。

ソース上でentityIdにCognitoのユーザ名を指定しているので、ログインしたユーザが異なれば取得できる結果が変わってきます。

アプリにアクセスしてみます。

ユーザ:cm-ogura でアクセスしたときはTrueが取得できています。

一方、ユーザ:cm-ogura-2でアクセスしたときはFalseが取得できています。

その他の機能

上記以外にも、

  • Variationの割当状況のグラフ表示
  • A/Bテスト向けのメトリクス収集
  • Variationのオーバーライド指定
    • 特定のユーザがアクセスした場合、必ずTrueを返す等が可能

などの機能があるようです。興味があるかたは、是非ドキュメント を見てみてください。

まとめ

Reactアプリを使って簡単に動作を検証してみました。

フィーチャーフラグの様な、ビジネスに直接は関係ないが、運用上必要になる機能がAWSマネージドで提供されるのは嬉しい方も多いのではないでしょうか。今後のアップデートにも期待したいですね。

参考