Python 機能管理
Python 機能管理ライブラリでは、機能フラグに基づいてアプリケーション機能を開発および公開する方法が提供されます。 新しい機能が開発されると、多くのアプリケーションでは、その機能を有効にすべきタイミングや、有効にすべきタイミングなど、特別な要件が発生します。 このライブラリでは、これらの関係を定義する方法が提供され、これらの機能を公開できるようにするために、一般的な Python コード パターンに統合されています。
機能フラグでは、Python アプリケーションで機能を動的にオンまたはオフにする方法が提供されます。 開発者は、条件付きステートメントのように簡単なユース ケースで機能フラグを使用できます。
Python 機能管理ライブラリを使用するメリットを次に示します。
機能管理のための一般的な規則
参入障壁の低さ
- JSON 機能フラグ設定のサポート
機能フラグの有効期間の管理
- 構成値はリアルタイムで変更できます。機能フラグは要求全体で整合性があります
シンプルなシナリオから複雑なシナリオまで対応
- 宣言型構成ファイルを通じた機能のオン/オフの切り替え
- サーバーへの呼び出しに基づいて機能の状態を動的に評価
Python 機能管理ライブラリはオープン ソースです。 詳細については、GitHub リポジトリを参照してください。
機能フラグ
機能フラグは、名前と、機能をオンにするための機能フィルターの一覧の 2 つで構成されます。
機能フィルター
機能フィルターは、機能を有効にする必要があるシナリオを定義します。 機能がオンかオフか評価される場合に、機能フィルターの一覧は、いずれかのフィルターがその機能を有効にする必要があると決定するまで走査されます。 この時点で、その機能は有効であるとみなされ、機能フィルターの走査は停止します。 どの機能フィルターも機能を有効にすることを示していない場合は、無効とみなされます。
例として、Microsoft Edge ブラウザーの機能フィルターを設計できます。 この機能フィルターは、HTTP 要求が Microsoft Edge から派生したものである限り、そのフィルターに接続されているすべての機能をアクティブにします。
機能フラグの構成
Python ディクショナリは、機能フラグを定義するために使用されます。 このディクショナリは、キーとしての機能名と、値として機能フラグ オブジェクトで構成されます。 機能フラグ オブジェクトは、conditions
キーを含むディクショナリであり、それ自体に client_filters
キーが含まれています。 client_filters
キーは、機能を有効にする必要があるかどうかを判断するために使用される機能フィルターの一覧です。
機能フラグの宣言
機能管理ライブラリでは、機能フラグ ソースとして 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
がオンになっているので、常に FeatureT
が true
を返すことがわかります。 FeatureU
は FeatureT
と同じですが、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 と評価される必要があることを意味します。
All
の requirement_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"
}
}
]
}
},
]
}
}
上記の例では、FeatureW
は All
の requirement_type
を指定します。つまり、その機能を有効にするには、すべてのフィルターが true と評価される必要があります。 この場合、指定された時間枠に 50% のユーザーに対してこの機能が有効になります。
従量課金プラン
機能管理の基本フォームは、機能フラグが有効かどうかを確認し、その結果に基づいてアクションを実行することです。 機能フラグの状態の確認は、FeatureManager
の is_enabled
メソッドを使用して行われます。
…
feature_manager = FeatureManager(feature_flags)
…
if feature_manager.is_enabled("FeatureX"):
# Do something
FeatureManager
に提供される feature_flags
は、AzureAppConfigurationProvider
または機能フラグのディクショナリにすることができます。
機能フィルターの実装
機能フィルターを作成すると、定義した条件に基づいて機能を有効にする方法を得られます。 機能フィルターを実装するには、FeatureFilter
インターフェイスを実装する必要があります。 FeatureFilter
には evaluate
という名前の単一のメソッドがあります。 機能が機能フィルターに対して有効であることを指定すると、evaluate
メソッドが呼び出されます。 evaluate
が true
を返す場合は、機能が有効になっていることを意味します。
次のスニペットは、カスタマイズされた機能フィルター MyCustomFilter
を追加する方法を示しています。
feature_manager = FeatureManager(feature_flags, feature_filters=[MyCustomFilter()])
機能フィルターは、FeatureManager
の作成時にプロパティ feature_filters
に指定することによって登録されます。 カスタム機能フィルターにコンテキストが必要な場合は、kwargs
を使用して is_enabled
を呼び出すときに渡すことができます。
フィルター Alias 属性
機能フラグの機能フィルターが登録されている場合、フィルターの名前は既定でエイリアスとして使用されます。
機能フィルターの識別子は、@FeatureFilter.alias("MyFilter")
を使用してオーバーライドできます。 機能フィルターをこの属性で装飾することで、機能フラグ内でこの機能フィルターを参照するために構成で使用する必要がある名前を宣言できます。
欠落した機能フィルター
機能が特定の機能フィルターに対して有効になるように構成されていて、その機能フィルターが登録されていない場合、機能の評価時に ValueError
例外が発生します。
組み込み機能フィルター
FeatureManagement
パッケージには、TimeWindowFilter
と TargetingFilter
の 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"
]
}
}
}
}
]
ターゲティング
対象設定は、開発者が新しい機能をユーザー ベースに段階的にロールアウトできるようにする機能管理戦略です。 この戦略は、対象ユーザーと呼ばれる一連のユーザーを対象設定するという概念に基づいて構築されています。 対象ユーザーは、特定のユーザー、グループ、除外されたユーザー/グループ、およびユーザー ベース全体の指定された割合で構成されます。 対象ユーザーに含まれるグループは、メンバーの合計数に対する割合にさらに分けることができます。
次の手順は、新しい「ベータ」機能の段階的なロールアウトの例を示しています。
- 個人ユーザーの Jeff と Alicia にベータ版へのアクセス権が付与されます
- 別のユーザーであるマークは、オプトイン要求をして、含まれました。
- 「Ring1」ユーザーと呼ばれるグループの 20% がベータ版に含まれています。
- ベータ版に含まれる「Ring1」ユーザーの数は、最大 100% 増加します。
- ユーザー ベースの 5% がベータに含まれています。
- ロールアウト率は最大 100% まで増加し、機能は完全にロールアウトされます。
機能をロールアウトするこの戦略では、これに含まれる Microsoft.Targeting 機能フィルターを通してライブラリに組み込まれています。
ユーザーを対象設定する
is_enabled
呼び出しでユーザーを直接指定するか、または TargetingContext
を使用してユーザーとオプションのグループを指定することができます。
# Directly specifying the user
result = is_enabled(feature_flags, "test_user")
# Using a TargetingContext
result = is_enabled(feature_flags, TargetingContext(user_id="test_user", groups=["Ring1"]))
対象設定の除外
対象ユーザーを定義する場合、ユーザーやグループを対象ユーザーから除外できます。 除外は、ある機能をユーザー グループにロールアウトする場合に、一部のユーザーまたはグループをロールアウトから除外する必要がある場合に役立ちます。 除外は、対象ユーザー Exclusion
プロパティにユーザーとグループの一覧を追加することで定義されます。
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
上記の例では、Jeff
と Alicia
という名前のユーザーに対してこの機能が有効になっています。 また、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
バリアントの取得
各機能について、FeatureManager
の get_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
のインスタンスから得られます。
バリアント機能フラグの宣言
通常の機能フラグと比較して、バリアント機能フラグには variants
と allocation
の 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
) に割り当てます。
この機能が有効になっている場合は、機能マネージャーは user
、group
、percentile
の割り当てを順番に確認してバリアントを割り当てます。 この具体的な例では、評価されるユーザーが Marsha
という名前で、Ring1
というグループに属する場合、またはユーザーが偶然 0 パーセンタイルと 10 パーセンタイルの間に存在する場合、指定されたバリアントがユーザーに割り当てられます。 この場合、割り当てられたユーザーはすべて Big
バリアントを返します。 これらの割り当てがどれも一致しない場合、default_when_enabled
のバリアントが割り当てられ、Small
になります。
割り当てのロジックは Microsoft.Targeting 機能フィルターと似ていますが、パラメーターには、ターゲット設定に存在するが割り当てに存在しないものや、その逆があります。 対象設定と割り当ての結果は関係ありません。
バリアントを使用する有効な状態のオーバーライド
機能フラグの有効な状態をオーバーライドするためにバリアントを使用できます。 オーバーライドにより、バリアントが機能フラグの評価を拡張する機会が付与されます。 バリアントのあるフラグに対して is_enabled
を呼び出すと、機能マネージャーは、現在のユーザーに割り当てられているバリアントが結果をオーバーライドするように構成されているかどうかを調べます。 オーバーライドは、省略可能なバリアント プロパティ status_override
を使用して行われます。 既定では、このプロパティは None
に設定されており、バリアントはフラグが有効か無効であるかに影響しないことを意味します。 status_override
を Enabled
に設定すると、バリアントが選択されたときにフラグをオーバーライドして有効にすることができます。 status_override
を Disabled
に設定すると逆の機能が提供され、バリアントが選択されたときにフラグが無効になります。 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_override
は Disabled
と等しいため、その機能は無効とみなされます。
テレメトリ
機能フラグの変更がデプロイされると、多くの場合、アプリケーションへの影響の分析が重要です。 たとえば、可能性のある質問は次のとおりです。
- 私のフラグは期待どおりに有効または無効になっていますか?
- 対象ユーザーは、期待どおりに特定の機能にアクセスできていますか?
- どのバリアントが特定のユーザーに表示されていますか?
この種の質問には、機能フラグ評価イベントの生成と分析を通じて回答できます。 このライブラリでは、必要に応じて 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 |
バリアントが割り当てられる理由。 |
次のステップ
アプリケーションで機能フラグを使用する方法については、次のクイックスタートに進んでください。
機能フィルターの使用方法について学ぶには、次のチュートリアルに進んでください。