Python 機能管理

機能の管理

機能の管理

Python 機能管理ライブラリでは、機能フラグに基づいてアプリケーション機能を開発および公開する方法が提供されます。 新しい機能が開発されると、多くのアプリケーションでは、その機能を有効にすべきタイミングや、有効にすべきタイミングなど、特別な要件が発生します。 このライブラリでは、これらの関係を定義する方法が提供され、これらの機能を公開できるようにするために、一般的な Python コード パターンに統合されています。

機能フラグでは、Python アプリケーションで機能を動的にオンまたはオフにする方法が提供されます。 開発者は、条件付きステートメントのように簡単なユース ケースで機能フラグを使用できます。

Python 機能管理ライブラリを使用するメリットを次に示します。

  • 機能管理のための一般的な規則

  • 参入障壁の低さ

    • JSON 機能フラグ設定のサポート
  • 機能フラグの有効期間の管理

    • 構成値はリアルタイムで変更できます。機能フラグは要求全体で整合性があります
  • シンプルなシナリオから複雑なシナリオまで対応

    • 宣言型構成ファイルを通じた機能のオン/オフの切り替え
    • サーバーへの呼び出しに基づいて機能の状態を動的に評価

    Python 機能管理ライブラリはオープン ソースです。 詳細については、GitHub リポジトリを参照してください。

機能フラグ

機能フラグは、名前と、機能をオンにするための機能フィルターの一覧の 2 つで構成されます。

機能フィルター

機能フィルターは、機能を有効にする必要があるシナリオを定義します。 機能がオンかオフか評価される場合に、機能フィルターの一覧は、いずれかのフィルターがその機能を有効にする必要があると決定するまで走査されます。 この時点で、その機能は有効であるとみなされ、機能フィルターの走査は停止します。 どの機能フィルターも機能を有効にすることを示していない場合は、無効とみなされます。

例として、Microsoft Edge ブラウザーの機能フィルターを設計できます。 この機能フィルターは、HTTP 要求が Microsoft Edge から派生したものである限り、そのフィルターに接続されているすべての機能をアクティブにします。

機能フラグの構成

Python ディクショナリは、機能フラグを定義するために使用されます。 このディクショナリは、キーとしての機能名と、値として機能フラグ オブジェクトで構成されます。 機能フラグ オブジェクトは、EnabledFor キーを含むディクショナリです。 EnabledFor キーは、機能を有効にする必要があるかどうかを判断するために使用される機能フィルターの一覧です。

機能フラグの宣言

機能管理ライブラリでは、機能フラグ ソースとして json がサポートされています。 以下は、JSON ファイルで機能フラグを設定するために使用される形式の例です。

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": "true"
            },
            {
                "id": "FeatureU",
                "enabled": "false"
            },
            {
                "id": "FeatureV",
                "enabled": "true",
                "conditions": {
                    "client_filters": [
                        {
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

JSON ドキュメントの feature_management セクションが機能フラグ設定を読み込むための慣例によって使用されます。 feature_flags セクションは、ライブラリに読み込まれる機能フラグの一覧です。 上記のセクションでは、3 つの異なる機能が見られます。 機能は、conditions の内部の client_filters プロパティを使用して機能フィルターを定義します。 FeatureT の機能フィルターでは、フィルターが定義されずに enabled がオンになっているので、常に FeatureTtrue を返すことがわかります。 FeatureUFeatureT と同じですが、enabled では false になり、機能が常に false を返します。 FeatureV は、Microsoft.TimeWindow という名前の機能フィルターを指定します。 FeatureV は構成可能な機能フィルターの例です。 フィルターに parameters プロパティがある例で確認できます。 parameters プロパティは、フィルターの構成に使用されます。 この場合、機能がアクティブになる開始時間と終了時間が構成されます。

feature_management セクションの詳細なスキーマはこちらで見つけることができます。

詳細設定: 機能フラグ名でのコロン ':' の使用は禁止されています。

宣言のオン/オフ

次のスニペットは、オン/オフ機能に使用できる機能を定義する別の方法を示しています。

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": "true"
            },
            {
                "id": "FeatureX",
                "enabled": "false"
            }
        ]
    }
}

Requirement_type

機能フラグの requirement_type プロパティは、フィルターが機能の状態を評価する場合に Any または All ロジックを使用する必要があるかどうかを決定するために使用されます。 requirement_type を指定しない場合の既定値は Any です。

  • Any は、1 つのフィルターだけが true と評価されると、その機能が有効になることを意味します。
  • All は、機能を有効にするために、すべてのフィルターが true と評価される必要があることを意味します。

Allrequirement_type は走査を変更します。 まず、フィルターがない場合、この機能は無効になります。 次に、フィルターのいずれかがその機能を無効にする必要があると判断するまで、機能フィルターが走査されます。 どのフィルターも機能を無効にすることを示していない場合は、有効とみなされます。

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureW",
                "enabled": "true",
                "conditions": {
                    "requirement_type": "All",
                    "client_filters": [
                        {
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                            }
                        },
                        {
                            "name": "Percentage",
                            "parameters": {
                                "Value": "50"
                            }
                        }
                    ]
                }
            },
        ]
    }
}

上記の例では、FeatureWAllrequirement_type を指定します。つまり、その機能を有効にするには、すべてのフィルターが true と評価される必要があります。 この場合、指定された時間枠に 50% のユーザーに対してこの機能が有効になります。

従量課金プラン

機能管理の基本フォームは、機能フラグが有効かどうかを確認し、その結果に基づいてアクションを実行することです。 機能フラグの状態の確認は、FeatureManageris_enabled メソッドを使用して行われます。

…
feature_manager = FeatureManager(feature_flags)
…
if feature_manager.is_enabled("FeatureX"):
    # Do something

FeatureManager に提供される feature_flags は、AzureAppConfigurationProvider または機能フラグのディクショナリにすることができます。

機能フィルターの実装

機能フィルターを作成すると、定義した条件に基づいて機能を有効にする方法を得られます。 機能フィルターを実装するには、FeatureFilter インターフェイスを実装する必要があります。 FeatureFilter には evaluate という名前の単一のメソッドがあります。 機能が機能フィルターに対して有効であることを指定すると、evaluate メソッドが呼び出されます。 evaluatetrue を返す場合は、機能が有効になっていることを意味します。

次のスニペットは、カスタマイズされた機能フィルター MyCriteriaFilter を追加する方法を示しています。

feature_manager = FeatureManager(feature_flags, feature_filters=[MyCustomFilter()])

機能フィルターは、FeatureManager の作成時にプロパティ feature_filters に指定することによって登録されます。 カスタム機能フィルターにコンテキストが必要な場合は、kwargs を使用して is_enabled を呼び出すときに渡すことができます。

フィルター Alias 属性

機能フラグの機能フィルターが登録されている場合、フィルターの名前は既定でエイリアスとして使用されます。

機能フィルターの識別子は、@FeatureFilter.alias("MyFilter") を使用してオーバーライドできます。 機能フィルターをこの属性で装飾することで、機能フラグ内でこの機能フィルターを参照するために構成で使用する必要がある名前を宣言できます。

欠落した機能フィルター

機能が特定の機能フィルターに対して有効になるように構成されていて、その機能フィルターが登録されていない場合、機能の評価時に ValueError 例外が発生します。

組み込み機能フィルター

FeatureManagement パッケージには、TimeWindowFilterTargetingFilter の 2 つの機能フィルターがあります。

組み込み機能フィルターにはそれぞれ独自のパラメーターがあります。 こちらは、機能フィルターの一覧と例です。

Microsoft.TimeWindow

このフィルターは、時間枠に基づいて機能を有効にする機能を提供します。 End のみ指定された場合、その時間までその機能はオンとみなされます。 Start のみ指定された場合、その時点以降のすべての時点で機能はオンとみなされます。

"client_filters": [
    {
        "name": "Microsoft.TimeWindow",
        "parameters": {
            "Start": "Wed, 01 May 2019 13:59:59 GMT",
            "End": "Mon, 01 Jul 2019 00:00:00 GMT"
        }
    }
]     

Microsoft.Targeting

このフィルターは、対象ユーザーに対して機能を有効にする機能を提供します。 対象設定の詳細については、以下の「対象設定」セクションで説明します。 フィルター パラメーターには、ユーザー、グループ、除外ユーザー/グループ、およびその機能にアクセスできるユーザーベースの既定の割合を記述する Audience オブジェクトが含まれます。 Groups セクションに一覧表示されている各グループ オブジェクトは、グループのメンバーの何パーセントがアクセスできるかも指定する必要があります。 ユーザーがExclusion セクションで指定されている場合、そのユーザーが直接指定されている場合、またはそのユーザーが除外されているグループに属している場合に、機能は無効になります。 それ以外の場合、Users セクションでユーザーが直接指定された場合、またはユーザーがいずれかのグループ ロールアウトの割合に含まれる場合、またはユーザーが既定ロールアウトの割合に含まれる場合、そのユーザーの機能が有効になります。

"client_filters": [
    {
        "name": "Microsoft.Targeting",
        "parameters": {
            "Audience": {
                "Users": [
                    "Jeff",
                    "Alicia"
                ],
                "Groups": [
                    {
                        "Name": "Ring0",
                        "RolloutPercentage": 100
                    },
                    {
                        "Name": "Ring1",
                        "RolloutPercentage": 50
                    }
                ],
                "DefaultRolloutPercentage": 20,
                "Exclusion": {
                    "Users": [
                        "Ross"
                    ],
                    "Groups": [
                        "Ring2"
                    ]
                }
            }
        }
    }
]

ターゲティング

対象設定は、開発者が新しい機能をユーザー ベースに段階的にロールアウトできるようにする機能管理戦略です。 この戦略は、対象ユーザーと呼ばれる一連のユーザーを対象設定するという概念に基づいて構築されています。 対象ユーザーは、特定のユーザー、グループ、除外されたユーザー/グループ、およびユーザー ベース全体の指定された割合で構成されます。 対象ユーザーに含まれるグループは、メンバーの合計数に対する割合にさらに分けることができます。

次の手順は、新しい「ベータ」機能の段階的なロールアウトの例を示しています。

  1. 個人ユーザーの Jeff と Alicia にベータ版へのアクセス権が付与されます
  2. 別のユーザーであるマークは、オプトイン要求をして、含まれました。
  3. 「Ring1」ユーザーと呼ばれるグループの 20% がベータ版に含まれています。
  4. ベータ版に含まれる「Ring1」ユーザーの数は、最大 100% 増加します。
  5. ユーザー ベースの 5% がベータに含まれています。
  6. ロールアウト率は最大 100% まで増加し、機能は完全にロールアウトされます。

機能をロールアウトするこの戦略では、これに含まれる Microsoft.Targeting 機能フィルターを通してライブラリに組み込まれています。

ユーザーを対象設定する

is_enabled 呼び出しでユーザーを直接指定するか、または TargetingContxt を使用してユーザーとオプションのグループを指定することができます。

# Directly specifying the user
feature_manager = FeatureManager(feature_flags, "test_user")

# Using a TargetingContext
feature_manager = FeatureManager(feature_flags, TargetingContext(user_id="test_user", groups=["Ring1"]))

対象設定の除外

対象ユーザーを定義する場合、ユーザーやグループを対象ユーザーから除外できます。 除外は、ある機能をユーザー グループにロールアウトする場合に、一部のユーザーまたはグループをロールアウトから除外する必要がある場合に役立ちます。 除外は、対象ユーザー Exclusion プロパティにユーザーとグループの一覧を追加することで定義されます。

"Audience": {
    "Users": [
        "Jeff",
        "Alicia"
    ],
    "Groups": [
        {
            "Name": "Ring0",
            "RolloutPercentage": 100
        }
    ],
    "DefaultRolloutPercentage": 0
    "Exclusion": {
        "Users": [
            "Mark"
        ]
    }
}

上記の例では、JeffAlicia という名前のユーザーに対してこの機能が有効になっています。 また、Ring0 という名前のグループのユーザーに対しても有効です。 ただし、ユーザーの名前が Mark である場合、そのユーザーがグループ Ring0 に属しているかに関係なく、機能は無効になります。 除外は対象設定フィルターの残りの部分よりも優先されます。

バリアント

アプリケーションに新しい機能が追加される場合、その機能に複数の異なる設計オプションがある場合があります。 設計を決定するための一般的な解決策は、一種の A/B テストです。 A/B テストは、ユーザー ベースの異なるセグメントに機能の異なるバージョンを提供し、ユーザー操作に基づいてバージョンを選択するものです。 このライブラリでは、機能のさまざまな構成をバリアントで表現することで、この機能が有効になります。

バリアントは、機能フラグを単なるオン/オフのフラグ以上のものにします。 バリアントは機能フラグの値を表し、文字列、数値、ブール値、あるいは構成オブジェクトである場合もあります。 バリアントを宣言する機能フラグは、それぞれのバリアントをどのような状況で使用する必要があるかを定義する必要があります。この詳細については、「バリアントの割り当て」セクションで扱っています。

class Variant:
    def __init__(self, name: str, configuration: Any):
        self._name = name
        self._configuration = configuration

    @property
    def name(self) -> str:
        """
        The name of the variant.
        :rtype: str
        """
        return self._name

    @property
    def configuration(self) -> Any:
        """
        The configuration of the variant.
        :rtype: Any
        """
        return self._configuration

バリアントの取得

各機能について、FeatureManagerget_variant メソッドを使用してバリアントを取得できます。

…
variant = print(feature_manager.get_variant("TestVariants", TargetingContext(user_id="Adam"))

variantConfiguration = variant.configuration;

// Do something with the resulting variant and its configuration

返されるバリアントは現在評価されているユーザーに依存し、その情報は TargetingContext のインスタンスから得られます。

バリアント機能フラグの宣言

通常の機能フラグと比較して、バリアント機能フラグには variantsallocation の 2 つの追加プロパティがあります。 variants プロパティは、この機能に対して定義されたバリアントを含む配列です。 allocation プロパティは、これらのバリアントを機能に割り当てる方法を定義します。 通常の機能フラグを宣言するのと同様に、バリアント機能フラグも JSON ファイルで設定できます。 こちらにバリアント機能フラグの例を示します。

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "enabled": true,
                "allocation": {
                    "default_when_enabled": "Small",
                    "group": [
                        {
                            "variant": "Big",
                            "groups": [
                                "Ring1"
                            ]
                        }
                    ]
                },
                "variants": [
                    { 
                        "name": "Big"
                    },  
                    { 
                        "name": "Small"
                    } 
                ]
            }
        ]
    }
}

バリアントの定義

各バリアントには名前と構成の 2 つのプロパティがあります。 名前は特定のバリアントを指すのに使われ、構成はそのバリアントの値です。 この構成は configuration_value プロパティを使用して設定できます。 configuration_value は、文字列、数値、論理値、構成オブジェクトのいずれかに設定できるインライン構成です。 configuration_value が指定されていない場合は、返されたバリアントの Configuration プロパティは None になります。

variants プロパティの下で、各機能に対して利用可能なすべてのバリアントのリストが定義されます。

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "variants": [
                    { 
                        "name": "Big", 
                        "configuration_value": {
                            "Size": 500
                        }
                    },  
                    { 
                        "name": "Small", 
                        "configuration_value": {
                            "Size": 300
                        }
                    } 
                ]
            }
        ]
    }
}

バリアントの割り当て

機能のバリアントを割り当てるプロセスは、機能の allocation プロパティによって決定されます。

"allocation": { 
    "default_when_enabled": "Small", 
    "default_when_disabled": "Small",  
    "user": [ 
        { 
            "variant": "Big", 
            "users": [ 
                "Marsha" 
            ] 
        } 
    ], 
    "group": [ 
        { 
            "variant": "Big", 
            "groups": [ 
                "Ring1" 
            ] 
        } 
    ],
    "percentile": [ 
        { 
            "variant": "Big", 
            "from": 0, 
            "to": 10 
        } 
    ], 
    "seed": "13973240" 
},
"variants": [
    { 
        "name": "Big", 
        "configuration_value": "500px"
    },  
    { 
        "name": "Small", 
        "configuration_value": "300px"
    } 
]

機能の allocation 設定には次のプロパティがあります。

プロパティ 説明
default_when_disabled 機能が無効とされている間にバリアントが要求された場合に使用するバリアントを指定します。
default_when_enabled 機能が有効であるとみなされ、他のバリアントがユーザーに割り当てられていない場合に、バリアントが要求されたときに使用するバリアントを指定します。
user バリアントと、そのバリアントを割り当てるユーザーの一覧を指定します。
group バリアントとグループの一覧を指定します。 バリアントは、ユーザーが少なくとも 1 つのグループに属している場合に割り当てられます。
percentile バリアントと、そのバリアントを割り当てるためにユーザーの計算されたパーセンテージの範囲を指定します。
seed percentile に対して計算されたパーセンテージの基になる値。 同じ seed 値が使用されている場合、特定のユーザーに対して計算されたパーセンテージはすべての機能で同じになります。 seed が指定されていない場合は、機能名に基づく既定のシードが作成されます。

機能が有効になっていない場合は、機能マネージャーは default_when_disabled とマークされたバリアントを現在のユーザー (この場合は Small) に割り当てます。

この機能が有効になっている場合は、機能マネージャーは usergrouppercentile の割り当てを順番に確認してバリアントを割り当てます。 この具体的な例では、評価されるユーザーが Marsha という名前で、Ring1 というグループに属する場合、またはユーザーが偶然 0 パーセンタイルと 10 パーセンタイルの間に存在する場合、指定されたバリアントがユーザーに割り当てられます。 この場合、割り当てられたユーザーはすべて Big バリアントを返します。 これらの割り当てがどれも一致しない場合、default_when_enabled のバリアントが割り当てられ、Small になります。

割り当てのロジックは Microsoft.Targeting 機能フィルターと似ていますが、パラメーターには、ターゲット設定に存在するが割り当てに存在しないものや、その逆があります。 対象設定と割り当ての結果は関係ありません。

バリアントを使用する有効な状態のオーバーライド

機能フラグの有効な状態をオーバーライドするためにバリアントを使用できます。 オーバーライドにより、バリアントが機能フラグの評価を拡張する機会が付与されます。 バリアントのあるフラグに対して is_enabled を呼び出すと、機能マネージャーは、現在のユーザーに割り当てられているバリアントが結果をオーバーライドするように構成されているかどうかを調べます。 オーバーライドは、省略可能なバリアント プロパティ status_override を使用して行われます。 既定では、このプロパティは None に設定されており、バリアントはフラグが有効か無効であるかに影響しないことを意味します。 status_overrideEnabled に設定すると、バリアントが選択されたときにフラグをオーバーライドして有効にすることができます。 status_overrideDisabled に設定すると逆の機能が提供され、バリアントが選択されたときにフラグが無効になります。 enabled 状態が false の機能はオーバーライドできません。

バイナリのバリアントで機能フラグを使用する場合、status_override プロパティが役立ちます。 これにより、アプリケーションで is_enabled のような API を使い続けながら、パーセンタイル割り当てやシードなどのバリアントに付属する新しい機能の恩恵を受けることができます。

{
    "id": "MyVariantFeatureFlag",
    "enabled": true,
    "allocation": {
        "percentile": [
            {
                "variant": "On",
                "from": 10,
                "to": 20
            }
        ],
        "default_when_enabled":  "Off",
        "seed": "Enhanced-Feature-Group"
    },
    "variants": [
        {
            "name": "On"
        },
        {
            "name": "Off",
            "status_override": "Disabled"
        }
    ]
}

上記の例では、機能が常に有効になっています。 現在のユーザーが計算されたパーセンタイルの 10 から 20 の範囲にある場合、On バリアントが返されます。 それ以外の場合は、Off バリアントが返され、status_overrideDisabled と等しいため、その機能は無効とみなされます。

テレメトリ

機能フラグの変更がデプロイされると、多くの場合、アプリケーションへの影響の分析が重要です。 たとえば、可能性のある質問は次のとおりです。

  • 私のフラグは期待どおりに有効または無効になっていますか?
  • 対象ユーザーは、期待どおりに特定の機能にアクセスできていますか?
  • どのバリアントが特定のユーザーに表示されていますか?

この種の質問には、機能フラグ評価イベントの生成と分析を通じて回答できます。 このライブラリでは、必要に応じて AzureMonitor が、OpenTelemetry を介した機能フラグの評価中にトレース テレメトリを生成できるようになります。

テレメトリの有効化

既定では、機能フラグにはテレメトリがありません。 指定された機能フラグに対してテレメトリを発行するには、フラグはテレメトリ生成のために有効であることを宣言する "必要があります"。

JSON で定義された機能フラグの場合は、telemetry プロパティを使用して有効化が行われます。

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyFeatureFlag",
                "enabled": true,
                "telemetry": {
                    "enabled": true
                }
            }
        ]
    }
}

上記のスニペットでは、テレメトリを有効にする MyFeatureFlag という名前の機能フラグを定義しています。 telemetry オブジェクトの enabled プロパティは、true に設定されます。 フラグのテレメトリを発行するには、enabled プロパティの値を true にする必要があります。

機能フラグの telemetry セクションには次のプロパティがあります。

プロパティ 説明
enabled 機能フラグに対してテレメトリを発行するかどうかを指定します。
metadata 機能フラグに関するカスタム メタデータを評価イベントに添付するために使用できる、辞書としてモデル化されたキーと値のペアのコレクション

さらに、FeatureManager を作成するときは、テレメトリ イベントを処理するためにコールバックを登録する必要があります。 このコールバックは、機能フラグが評価され、そのフラグに対してテレメトリが有効になっているたびに呼び出されます。

feature_manager = FeatureManager(feature_flags, on_feature_evaluated=publish_telemetry)

Application Insights Telemetry

機能管理ライブラリには、Application Insights に機能フラグ評価データを送信する組み込みのテレメトリ パブリッシャーが用意されています。 Application Insights を有効にするには、pip install FeatureManagement[AzureMonitor] を介して Azure Monitor と共に機能管理ライブラリをインストールできます。 このコマンドは、OpenTelemetry を使用して Application Insights にテレメトリのスタイルを設定するために使用される azure-monitor-events-extension パッケージをインストールします。

Note

azure-monitor-events-extension パッケージは、テレメトリを Open Telemetry パイプラインに追加するだけです。 Application Insights の登録が引き続き必要です。

from azure.monitor.opentelemetry import configure_azure_monitor

configure_azure_monitor(
        connection_string="InstrumentationKey=00000000-0000-0000-0000-000000000000"
    )

カスタム テレメトリの発行

テレメトリ コールバックは関数であるため、目的の宛先にテレメトリを発行するようにカスタマイズできます。 たとえば、テレメトリは、ログ サービス、データベース、またはカスタム テレメトリ サービスに発行できます。

機能フラグが評価され、テレメトリが有効になると、機能マネージャーは、EvaluationEvent パラメーターを使用してテレメトリ コールバックを呼び出します。 EvaluationEvent には次のプロパティが含まれます。

タグ 説明
feature 使用する機能フラグ。
user 対象設定に使用されるユーザー ID。
enabled 機能フラグが有効であると評価されるかどうか。
Variant 割り当てられたバリアント。
VariantAssignmentReason バリアントが割り当てられる理由。

次のステップ

アプリケーションで機能フラグを使用する方法については、次のクイックスタートに進んでください。

機能フィルターの使用方法について学ぶには、次のチュートリアルに進んでください。

バリアント機能フラグを使用して実験を実行する方法については、次のチュートリアルに進んでください。