Amazon Web Services ブログ

新機能 – Amazon CloudWatch Evidently – 実験と機能の管理

デベロッパーとして、Amazon CloudWatch Evidently の提供開始を発表できることを嬉しく思います。これは Amazon CloudWatch の新機能です。この機能を使用することで、デベロッパーはアプリケーションコードに実験や機能管理を簡単に導入できます。CloudWatch Evidently は、機能フラグとしても知られているダークローンチの実装と A/B テストという 2 つの似て非なるユースケースに使用できます。

機能フラグは、コードをデプロイせずに機能を有効または無効にできるソフトウェア開発手法です。機能のデプロイとリリースは切り離されます。コード内の機能は、実際のリリースに先立ってデプロイされます。それらは if-then-else 文の後ろに隠れたままとなります。ランタイムにおいて、アプリケーションコードはリモートサービスに対してクエリを実行します。このサービスは、新機能を利用できるユーザーの割合を決定します。ベータテスターなど、特定の顧客向けにアプリケーションの動作を設定することもできます。

機能フラグを使用すると、起動前に新しいコードをデプロイできます。その後、段階的に、少数の顧客が新機能を利用できるようにすることができます。リリースの際に、技術メトリクスとビジネスメトリクスをモニタリングします。すべてがうまくいけば、トラフィックを増やして、他のユーザーに対しても新しい機能を利用可能にすることができます。問題が発生した場合は、1 回クリックするか API コールを実行するだけでサーバー側のルーティングを変更して、古い (かつ作業中の) エクスペリエンスのみを顧客が利用できるようにすることができます。これにより、ロールバックデプロイを必要とせずにユーザーエクスペリエンスを元に戻すことができます。

A/B テストは、機能フラグと多くの点で類似していますが、目的は異なります。A/B テストは、複数のバリエーションを持つランダム化された実験で構成されます。A/B テストでは、1 つの機能の複数のバージョンを比較できます。通常、バリエーション A の対象の応答をバリエーション B と比較してテストし、どちらがより効果的かを判断します。例えば、e コマースのウェブサイトを想像してみましょう (Amazon では非常によく知られているシナリオです)。チェックアウトボタンのさまざまな形状、サイズ、または色を実験して、収益に最も大きな影響を与えているバリエーションを測定したいと考えるかもしれません。

A/B テストを実施するために必要なインフラストラクチャは、機能フラグに必要なインフラストラクチャと似ています。アプリケーションで複数のシナリオをデプロイし、顧客のトラフィックのどの部分をどのシナリオにルーティングするかをコントロールします。その後、詳細な統計分析を実行して、バリエーションの影響を比較します。CloudWatch Evidently は、高度な統計知識を必要とせずに、実験結果の解釈とそれに基づく対応をサポートします。実験の進行中は、いつでも p 値信頼区間などの Evidently の統計エンジンによって提供されるインサイトを使用して意思決定を行うことができます。

Amazon では、起動を制御するために機能フラグを幅広く使用し、A/B テストを使用して新しいアイデアを実験しています。当社では、デベロッパーのツールやライブラリの構築、および実験サービスの大規模な維持および運用について、長年にわたって経験を積んできました。そして今、当社の経験をお客様にご活用いただけるようになりました。

CloudWatch Evidently は、機能フラグに「起動」、A/B テストに「実験」という用語を使用していますので、これ以降、この記事でもその用法に従います。

アプリケーションデベロッパーの視点から見てみましょう。

実際の起動
このデモでは、単純なゲストブックウェブアプリケーションを使用します。これまで、ゲストブックのページは読み取り専用となっており、コメントはバックエンドからのみ入力されています。ゲストブックのページにお客様がコメントを入力できるようにする新機能を開発しました。この新機能を 1 週間かけて段階的に起動し、重要な技術メトリクスやビジネスメトリクス (p95 レイテンシー、カスタマーエンゲージメント、ページビューなど) に影響する場合には変更を元に戻せるようにしておきたいと考えています。ユーザーは認証され、ユーザー ID に基づいてユーザーをセグメント化します。

起動前:
Evidently - 実験オフ
起動後:
Evidently - 実験オン

プロジェクトを作成する
まずは Evidently の設定から始めましょう。AWS マネジメントコンソールを開き、CloudWatch Evidently に移動します。その後、[Create a project] (プロジェクトを作成) を選択します。

Evidently - プロジェクトを作成

[Project name] (プロジェクト名) と [Description] (説明) を入力します。

Evidently では、イベントを CloudWatch Logs または S3 に保存して、分析オペレーションを実行するために Amazon Redshift などのシステムに移動できるようにすることもできます。このデモでは、イベントを保存しないことを選択します。完了したら、[Create project] (プロジェクトを作成) を選択します。

Evidently - プロジェクトを作成 (第 2 部)

機能を追加する
次に、[Add feature] (機能を追加) を選択して、このプロジェクトの機能を作成します。[Feature name] (機能名) と [Feature description] (機能の説明) を入力します。次に、[Feature variations] (機能のバリエーション) を定義します。 この例では、2 つのバリエーションがあり、ブール型を使用します。true はゲストブックが編集可能であることを示し、false はゲストブックが読み取り専用であることを示します。バリエーションの種類には、ブール型浮動小数点数型long 型文字列型があります。

Evidently - 機能を作成オーバーライドを定義する場合もあります。オーバーライドにより、選択したユーザー用のバリエーションを事前に定義できます。ベータテスターのユーザー「seb」に編集可能なバリエーションを常に受け取ってもらいたいと考えています。

Evidently - 機能を作成 - オーバーライドコンソールは、アプリケーションに追加する JavaScript および Java コードスニペットを共有します。

Evidently - コードスニペットコードスニペットに言及したついでに、コードレベルでの変更を見てみましょう。

アプリケーションコードのインストルメント化
このデモでは、シンプルなウェブアプリケーションを使用します。このアプリケーションは JavaScript を使用してコーディングしました。AWS SDK for JavaScriptWebpack を使用してコードをパッケージ化しています。また、JQuery を使用して DOM を操作し、要素を非表示にしたり、表示したりします。この例がすべての人に役立つようにするため、このアプリケーションは、標準の JavaScript と最小限のフレームワークを使用するように設計されています。実際のプロジェクトでは、ReactAngular など、より高いレベルのツールやフレームワークを自由に使用してください。

まず、Evidently クライアントを初期化します。他の AWS のサービスと同様に、認証のためにアクセスキーとシークレットアクセスキーを提供する必要があります。ここでは認証の部分は割愛します。この記事の末尾に、お客様が利用可能なオプションについて説明するためのメモを追加しました。この例では、Amazon Cognito アイデンティティプールを使用して一時的な認証情報を受け取ります。

// Amazon CloudWatch Evidently クライアントを初期化します
const evidently = new AWS.Evidently({
    endpoint: EVIDENTLY_ENDPOINT,
    region: 'us-east-1',
    credentials: fromCognitoIdentityPool({
        client: new CognitoIdentityClient({ region: 'us-west-2' }),
        identityPoolId: IDENTITY_POOL_ID
    }),
});

このクライアントを備えた私のコードは、顧客に表示するバリエーションを決定するために EvaluateFeature API を呼び出すことがあります。entityId は、顧客をセグメント化するための文字列ベースの属性です。これは、セッション ID、顧客 ID、あるいは (より良いことに) これらのハッシュであることもあります。featureName パラメータには、評価する機能の名前が含まれます。この例では、EditableGuestBook という値を渡します。

const evaluateFeature = async (entityId, featureName) => {

    // API リクエスト構造
    const evaluateFeatureRequest = {
        // 評価機能 API を呼び出すための entityId
        entityId: entityId,
        // 機能の名前
        feature: featureName,
        // /プロジェクトの名前
        project: "AWSNewsBlog",
    };

    // 機能を評価します
    const response = await evidently.evaluateFeature(evaluateFeatureRequest).promise();
    console.log(response);
    return response;
}

応答には、サーバー側で定義されたトラフィックルールに基づく、Evidently からの割り当て決定が含まれます。

{
 details: {
   launch: "EditableGuestBook", group: "V2"},
   reason: "LAUNCH_RULE_MATCH",
   value: {boolValue: false},
   variation: "readonly"
}}

最後の部分は、上記で受け取った value に基づいて、ユーザーインターフェイスの一部を非表示または表示することです。基本的な JQuery の DOM 操作を使用すると、次のようになります。

window.aws.evaluateFeature(entityId, 'EditableGuestbook').then((response, error) => {
    if (response.value.boolValue) {
        console.log('Feature Flag is on, showing guest book');
        $('div#guestbook-add').show();
    } else {
        console.log('Feature Flag is off, hiding guest book');
        $('div#guestbook-add').hide();
    }
});

起動を作成
この機能がサーバー側で定義され、クライアントコードがインストルメント化されたので、コードをデプロイして顧客に公開します。後の段階で、この機能を起動することにするかもしれません。コンソールに戻り、自分のプロジェクトを選択し、[Create Launch] (起動を作成) を選択します。起動の [Launch name] (起動名) と [Launch description] (起動の説明) を入力します。その後、起動したい機能を [select] (選択) します。

Evidently - 起動を作成[Launch Configuration] (起動設定) セクションで、各バリエーションに送信されるトラフィックの量を設定します。また、複数のステップで起動をスケジュールすることもできます。これにより、スケジュールに基づいてルーティングのさまざまなステップを計画できます。例えば、初日にトラフィックの 10% を新機能に送り、2 日目には 20% を送る、というようなことができます。この例では、トラフィックを 50/50 に分けることにしました。

Evidently - 起動設定最後に、バリエーションのパフォーマンスを測定するために、最大 3 つのメトリクスを定義できます。メトリクスは、データイベントにルールを適用することで定義されます。

Evidently - カスタムメトリクスもう一度、PutProjectEvents API を使用してこれらのメトリクスを Evidently から送信するには、コードをインストルメント化する必要があります。起動が作成されると、EvaluateFeature API は entityId (このデモではユーザー) の値ごとに異なる値を返します。

ルーティング設定はいつでも変更できます。さらに、モニタリングダッシュボードにアクセスして、バリエーションのディストリビューションと各バリエーションのメトリクスを確認することもできます。

Evidently - 起動モニタリング私はこの投稿を書くためだけにグラフを作成したので、お客様の実際の起動グラフには私のグラフよりも多くのデータが表示されることでしょう。

A/B テスト
A/B テストの実行も同様です。テストする機能を作成し、[Experiment] (実験) を作成します。トラフィックの一部をバリエーション 1 に、もう一方をバリエーション 2 にルーティングするように実験を設定します。実験を起動する準備ができたら、[実験を開始] をはっきりと選択します。

Evidently - 実験を開始

この実験で関心があるのはカスタムメトリクスの送信です。以下に例を示します。

// pageLoadTime カスタムメトリクス
const timeSpendOnHomePageData = `{
   "details": {
      "timeSpendOnHomePage": ${timeSpendOnHomePageValue}
   },
   "userDetails": { "userId": "${randomizedID}", "sessionId": "${randomizedID}" }
}`;

const putProjectEventsRequest: PutProjectEventsRequest = {
   project: 'AWSNewsBlog',
   events: [
    {
        timestamp: new Date(),
        type: 'aws.evidently.custom',
        data: JSON.parse(timeSpendOnHomePageData)
    },
   ],
};

this.evidently.putProjectEvents(putProjectEventsRequest).promise().then(res =>{})

[Results] (結果) ページに切り替えると、[Event Count] (イベント数)、[Total Value] (合計値)、[Average] (平均)、[Improvement] (改善) (95% の信頼区間)、および [Statistical significance] (統計的有意性) の生の値とグラフデータが表示されます。統計的有意性は、ベースラインと比較して、バリエーションがメトリクスに及ぼす影響がどの程度確実であるかを表します。

これらの結果は実験全体を通じて生成され、信頼区間と統計的有意性は、表示したいときにいつでも有効にできます。さらに、実験の最後に、Evidently は実験のベイズ確率の視点も生成します。これは、バリエーション間に差が存在する可能性がどの程度あるかについての情報を提供するものです。

次の 2 つのスクリーンショットは、時間の経過に伴う 2 つのメトリクスの平均値と、95% の信頼区間内のメトリクスの改善を示すグラフを示しています。

Evidently - 実験モニタリング - 平均値Evidently - 実験モニタリング - 改善

その他の考慮事項
この記事を締めくくる前に、いくつかの追加の考慮事項を共有したいと思います。

まず、私は、フロントエンドアプリケーション開発のコンテキストにおいて Evidently のデモを選択したことをご理解いただくことが重要です。ただし、Evidently は、フロントエンドウェブまたはモバイル、バックエンド API、さらには機械学習 (ML) など、あらゆるアプリケーションタイプで使用できます。例えば、Evidently を使用して 2 つの異なる機械学習モデルをデプロイし、上記で示したように実験を行うことができます。

2 つ目に、他の AWS のサービスと同様に、Evidently API は当社のすべての AWS SDK でご利用いただけます。これにより、EvaluateFeature およびその他の 9 つのプログラミング言語 (C++、Go、Java、JavaScript (および Typescript)、.Net、NodeJS、PHP、Python、および Ruby) の他の API を使用できます。Rust と Swift のための AWS SDK は開発中です。

3 つ目に、この記事でデモを行ったフロントエンドアプリケーションでは、Evidently API への呼び出しを認証する方法を検討することが重要です。アクセスキーとシークレットアクセスキーをハードコーディングすることはできません。フロントエンドのシナリオでは、Amazon Cognito アイデンティティプールを使用して、ユーザーアイデンティティトークンを一時的なアクセスおよびシークレットキーと交換することをお勧めします。ユーザーアイデンティティトークンは、Cognito ユーザープール、または Active DirectoryLogin with AmazonLogin with FacebookLogin with GoogleSignin with Apple などのサードパーティーの認証システム、もしくは OpenID ConnectSAML に準拠したシステムから取得できます。Cognito アイデンティティプールでは、匿名アクセスも許可されています。アイデンティティトークンは必要ありません。Cognito アイデンティティプールは、IAM ロールに関連付けられた一時トークンを提供します。ポリシーで evidently:EvaluateFeature API に対する呼び出しを Allow する必要があります。

最後に、機能フラグを使用する場合は、スプリント中にコードのクリーンアップ時間を設けることを計画してください。機能が起動したら、EvaluateFeature API に対する呼び出しと、その機能を最初に非表示にするために使用された if-then-else ロジックを削除することをお勧めします。

料金と利用可能なリージョン
Amazon Cloudwatch は、米国東部 (バージニア北部)、米国東部 (オハイオ)、米国西部 (オレゴン)、アジアパシフィック (シンガポール)、アジアパシフィック (シドニー)、アジアパシフィック (東京)、欧州 (アイルランド)、欧州 (フランクフルト)、および欧州 (ストックホルム) といった 9 つの AWS リージョンで一般的にご利用いただけます。いつもどおり、今後数か月以内に他のリージョンにも徐々に拡大する予定です。

従量制料金で、最低料金や定期的な料金はかかりません。CloudWatch Evidently は、Evidently のイベントと Evidently の分析ユニットに基づいてアカウントに料金を請求します。Evidently の分析ユニットは、Evidently で作成したルールに基づいて、Evidently イベントから生成されます。例えば、ユーザーのチェックアウトイベントでは、チェックアウト金額とカート内の商品数という 2 つの Evidently の分析ユニットが生成されます。料金の詳細については、Amazon CloudWatch の料金をご覧ください。

今すぐ CloudWatch Evidently で実験を開始しましょう!

— seb

原文はこちらです。