.NET 機能管理
.NET 機能管理ライブラリでは、機能フラグに基づいてアプリケーション機能を開発および公開する方法が提供されます。 新しい機能が開発されると、多くのアプリケーションでは、その機能を有効にすべきタイミングや、有効にすべきタイミングなど、特別な要件が発生します。 このライブラリでは、これらの関係を定義する方法が提供され、これらの機能を公開できるようにするために、一般的な .NET コード パターンに統合されています。
機能フラグでは、.NET および ASP.NET Core アプリケーションで機能を動的にオンまたはオフにする方法が提供されます。 開発者は、条件付きステートメントのように簡単なユース ケースから、ルートや MVC フィルターを条件付きで追加するような高度なシナリオまで、機能フラグを使用できます。 機能フラグは、.NET Core 構成システム上に構築されます。 任意の .NET Core 構成プロバイダーは、機能フラグのバックボーンとして機能させることができます。
.NET 機能管理ライブラリを使用するメリットを次に示します。
機能管理のための一般的な規則
参入障壁の低さ
IConfiguration
上への構築- JSON ファイル機能フラグ設定のサポート
機能フラグの有効期間の管理
- 構成値はリアルタイムで変更できます。機能フラグは要求全体で整合性があります
シンプルなシナリオから複雑なシナリオまで対応
- 宣言型構成ファイルを通じた機能のオン/オフの切り替え
- サーバーへの呼び出しに基づいて機能の状態を動的に評価
ASP.NET Core と MVC フレームワーク用の API 拡張
- ルーティング
- フィルター
- Action 属性
.NET 機能管理ライブラリはオープン ソースです。 詳細については、GitHub リポジトリを参照してください。
機能フラグ
機能フラグは、名前と、機能をオンにするための機能フィルターの一覧の 2 つで構成されます。
機能フィルター
機能フィルターは、機能を有効にする必要があるシナリオを定義します。 機能がオンかオフか評価される場合に、機能フィルターの一覧は、いずれかのフィルターがその機能を有効にする必要があると決定するまで走査されます。 この時点で、その機能は有効であるとみなされ、機能フィルターの走査は停止します。 どの機能フィルターも機能を有効にすることを示していない場合は、無効とみなされます。
例として、Microsoft Edge ブラウザーの機能フィルターを設計できます。 この機能フィルターは、HTTP 要求が Microsoft Edge から派生したものである限り、そのフィルターが接続されているすべての機能をアクティブにします。
機能フラグの構成
.NET Core 構成システムは、機能フラグの状態を決定するために使用されます。 このシステムの基盤は IConfiguration
です。 IConfiguration
の任意のプロバイダーは、機能フラグ ライブラリ用の機能状態プロバイダーとして使用できます。 このシステムは、appsettings.json から Azure App Configuration などまでの範囲のシナリオを有効にします。
機能フラグの宣言
機能管理ライブラリは、.NET Core の IConfiguration
システムのプロバイダーであるため、機能フラグ ソースとして appsettings.json をサポートしています。 以下は、json ファイルで機能フラグを設定するために使用される形式の例です。
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in a json file
"FeatureManagement": {
"FeatureT": {
"EnabledFor": [
{
"Name": "AlwaysOn"
}
]
},
"FeatureU": {
"EnabledFor": []
},
"FeatureV": {
"EnabledFor": [
{
"Name": "TimeWindow",
"Parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
}
}
}
JSON ドキュメントの FeatureManagement
セクションが機能フラグ設定を読み込むための慣例によって使用されます。 上記のセクションでは、3 つの異なる機能が見られます。 機能は EnabledFor
プロパティを使用して機能フィルターを定義します。 FeatureT
用の機能フィルターには、AlwaysOn
があります。 この機能フィルターは組み込みであり、指定されると常にその機能が有効になります。 AlwaysOn
機能フィルターでは構成が必要ないため、Name
プロパティしかありません。 FeatureU
はその EnabledFor
プロパティにフィルターがないため、有効になることはありません。 この機能が有効であることに依存する機能は、機能フィルターが空のままである限りアクセスできません。 ただし、機能を有効にする機能フィルターが追加されると、すぐに機能を開始します。 FeatureV
は、TimeWindow
という名前の機能フィルターを指定します。 これは構成可能な機能フィルターの例です。 フィルターに Parameters
プロパティがある例で確認できます。 これは、フィルターの構成に使用されます。 この場合、機能がアクティブになる開始時間と終了時間が構成されます。
FeatureManagement
セクションの詳細なスキーマはこちらで見つけることができます。
詳細設定: 機能フラグ名でのコロン ':' の使用は禁止されています。
宣言のオン/オフ
次のスニペットは、オン/オフ機能に使用できる機能を定義する別の方法を示しています。
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in config file
"FeatureManagement": {
"FeatureT": true, // On feature
"FeatureX": false // Off feature
}
}
RequirementType
機能フラグの RequirementType
プロパティは、フィルターが機能の状態を評価する場合に Any
または All
ロジックを使用する必要があるかどうかを決定するために使用されます。 RequirementType
を指定しない場合の既定値は Any
です。
Any
は、1 つのフィルターだけが true と評価されると、その機能が有効になることを意味します。All
は、機能を有効にするために、すべてのフィルターが true と評価される必要があることを意味します。
All
の RequirementType
は走査を変更します。 まず、フィルターがない場合、この機能は無効になります。 次に、フィルターのいずれかがその機能を無効にする必要があると判断するまで、機能フィルターが走査されます。 どのフィルターも機能を無効にすることを示していない場合は、有効とみなされます。
"FeatureW": {
"RequirementType": "All",
"EnabledFor": [
{
"Name": "TimeWindow",
"Parameters": {
"Start": "Mon, 01 May 2023 13:59:59 GMT",
"End": "Sat, 01 Jul 2023 00:00:00 GMT"
}
},
{
"Name": "Percentage",
"Parameters": {
"Value": "50"
}
}
]
}
上記の例では、FeatureW
は All
の RequirementType
を指定します。つまり、その機能を有効にするには、すべてのフィルターが true と評価される必要があります。 この場合、指定された時間枠に 50% のユーザーに対してこの機能が有効になります。
Microsoft 機能管理スキーマ
機能管理ライブラリは、機能フラグを宣言するための Microsoft Feature Management schema
の使用もサポートしています。 このスキーマは言語を選ばず、すべての Microsoft 機能管理ライブラリでサポートされています。
{
"feature_management": {
"feature_flags": [
{
"id": "FeatureT",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Mon, 01 May 2023 13:59:59 GMT",
"End": "Sat, 01 Jul 2023 00:00:00 GMT"
}
}
]
}
}
]
}
}
Note
構成内で feature_management
セクションが見つかると、FeatureManagement
セクションは無視されます。
機能管理ライブラリは、.NET Core の IConfiguration
システムのプロバイダーであるため、機能フラグ ソースとして appsettings.json をサポートしています。 機能フラグは Microsoft Feature Management schema
を使用して宣言されます。 このスキーマは言語を選ばず、すべての Microsoft 機能管理ライブラリでサポートされています。
以下は、json ファイルで宣言する機能フラグの例です。
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in a json file
"feature_management": {
"feature_flags": [
{
"id": "FeatureT",
"enabled": false
},
{
"id": "FeatureU",
"enabled": true,
"conditions": {}
},
{
"id": "FeatureV",
"enabled": true,
"conditions": {
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Mon, 01 May 2023 13:59:59 GMT",
"End": "Sat, 01 July 2023 00:00:00 GMT"
}
}
]
}
}
]
}
}
JSON ドキュメントの feature_management
セクションが機能フラグ設定を読み込むための慣例によって使用されます。 機能フラグ オブジェクトは、feature_management
セクションの feature_flags
配列に一覧表示されている必要があります。 上記のセクションでは、3 つの異なる機能が提供されていることを確認できます。 機能フラグには id
および enabled
プロパティがあります。 id
は、機能フラグを特定および参照するために使用される名前です。 enabled
プロパティは、機能フラグの有効な状態を指定します。 enabled
が false である場合、機能は [オフ] です。 enabled
が true である場合は、機能の状態は conditions
に依存します。 conditions
がない場合は [オン] になります。 conditions
があり、それが満たされている場合は、機能は [オン] です。 conditions
があり、それが満たされていない場合は、機能は [オフ] です。 conditions
プロパティは、機能を動的に有効にするための条件を宣言します。 機能は client_filters
配列で機能フィルターを定義します。 FeatureV
は、Microsoft.TimeWindow
という名前の機能フィルターを指定します。 これは構成可能な機能フィルターの例です。 フィルターに Parameters
プロパティがある例で確認できます。 これは、フィルターの構成に使用されます。 この場合、機能がアクティブになる開始時間と終了時間が構成されます。
詳細設定: 機能フラグ名でのコロン ':' の使用は禁止されています。
RequirementType
conditions
の requirement_type
プロパティは、フィルターが機能の状態を評価する場合に Any
または All
ロジックを使用する必要があるかどうかを決定するために使用されます。 requirement_type
を指定しない場合の既定値は Any
です。
Any
は、1 つのフィルターだけが true と評価されると、その機能が有効になることを意味します。All
は、機能を有効にするために、すべてのフィルターが true と評価される必要があることを意味します。
All
の requirement_type
は走査を変更します。 まず、フィルターがない場合、この機能は無効になります。 次に、フィルターがある場合は、フィルターのいずれかがその機能を無効にする必要があると判断するまで、機能フィルターが走査されます。 どのフィルターも機能を無効にすることを示していない場合は、有効とみなされます。
{
"id": "FeatureW",
"enabled": true,
"conditions": {
"requirement_type": "All",
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Mon, 01 May 2023 13:59:59 GMT",
"End": "Sat, 01 Jul 2023 00:00:00 GMT"
}
},
{
"name": "Microsoft.Percentage",
"parameters": {
"Value": "50"
}
}
]
}
}
上記の例では、FeatureW
は All
の requirement_type
を指定します。つまり、その機能を有効にするには、すべてのフィルターが true と評価される必要があります。 この場合、指定された時間枠に 50% のユーザーに対してこの機能が有効になります。
.NET 機能管理スキーマ
以前のバージョンでは、機能管理ライブラリのプライマリ スキーマは .NET feature management schema
でした。 v4.0.0 以降は、バリアントとテレメトリを含む新しい機能は、.NET 機能管理スキーマではサポートされません。
Note
feature_management
と FeatureManagement
の両セクションに存在する機能フラグ宣言がある場合は、feature_management
セクションのものが採用されます。
従量課金
機能管理の基本フォームは、機能フラグが有効かどうかを確認し、その結果に基づいてアクションを実行することです。 これは IFeatureManager
の IsEnabledAsync
メソッドを通じて行われます。
…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
// Do something
}
サービス登録
機能管理は、.NET Core の依存関係の挿入に依存します。 機能管理サービスは、標準の規則を使用して登録できます。
using Microsoft.FeatureManagement;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
}
}
機能マネージャーは、既定では .NET Core 構成データの "FeatureManagement" セクションから機能フラグの構成を取得します。 "FeatureManagement" セクションが存在しない場合、構成は空とみなされます。
Note
AddFeatureManagement
にセクションを渡すことで、機能フラグ構成を別の構成セクションから取得するように指定することもできます。 次の例では、代わりに "MyFeatureFlags" という別のセクションから読み取るように機能マネージャーに指示しています。
services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));
依存関係の挿入
機能管理ライブラリを MVC で使用する場合、IFeatureManager
は依存関係の挿入を通じて取得できます。
public class HomeController : Controller
{
private readonly IFeatureManager _featureManager;
public HomeController(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
}
範囲指定された機能管理サービス
AddFeatureManagement
メソッドは、アプリケーション内でシングルトンとして機能管理サービスを追加しますが、代わりに、範囲指定されたサービスとして機能管理サービスを追加する必要があるシナリオもあります。 たとえば、ユーザーは、コンテキスト情報のために範囲指定されたサービスを消費する機能フィルターを使用する場合があります。 この場合、代わりに AddScopedFeatureManagement
メソッドを使用する必要があります。 これにより、機能フィルターを含む機能管理サービスが範囲指定されたサービスとして追加されます。
services.AddScopedFeatureManagement();
ASP.NET Core 統合
機能管理ライブラリは、ASP.NET Core と MVC で機能を提供し、Web アプリケーションで一般的な機能フラグ シナリオを有効にします。 これらの機能は Microsoft.FeatureManagement.AspNetCore NuGet パッケージを参照することで使用できます。
コントローラーとアクション
MVC コントローラーとアクションを実行するためには、指定した機能 (あるいは任意の機能リストのいずれか) を有効にする必要があります。 これは Microsoft.FeatureManagement.Mvc
名前空間にある FeatureGateAttribute
を使用することで実行できます。
[FeatureGate("FeatureX")]
public class HomeController : Controller
{
…
}
上記の HomeController
は "FeatureX "によって限定されます。 "FeatureX" は HomeController
に含まれるアクションが実行される前に有効になっている必要があります。
[FeatureGate("FeatureX")]
public IActionResult Index()
{
return View();
}
上記の Index
MVC アクションは、実行する前に "FeatureX" が有効になっている必要があります。
無効なアクションの処理
指定した機能が有効でないために MVC コントローラーやアクションがブロックされると、登録された IDisabledFeaturesHandler
が呼び出されます。 既定では、HTTP 404 を返す最小限のハンドラーが登録されています。 これは、機能フラグを登録する場合に IFeatureManagementBuilder
を使用して上書きできます。
public interface IDisabledFeaturesHandler
{
Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}
表示
MVC ビューでは、<feature>
タグを使用して、機能フラグが有効か無効かに基づいてコンテンツを条件付きでレンダリングできます。
<feature name="FeatureX">
<p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
また、ある機能や機能のセットが無効になっている場合に、タグ ヘルパーの評価を無効にしてコンテンツを表示することもできます。 以下の例で negate="true"
を設定することで、FeatureX
が無効な場合にのみコンテンツがレンダリングされます。
<feature negate="true" name="FeatureX">
<p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
<feature>
タグは、name
属性でカンマ区切りの機能の一覧を指定することで、複数の機能を参照できます。
<feature name="FeatureX,FeatureY">
<p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
既定では、機能タグがレンダリングされるには、一覧表示されたすべての機能が有効になっている必要があります。 この動作は、以下の例のように requirement
属性を追加することでオーバーライドできます。
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
MVC ビューでは、<feature>
タグを使用して、機能フラグが有効か無効か、または機能の特定のバリアントが割り当てられているかに基づいてコンテンツを条件付きでレンダリングできます。 詳しくは、「バリアント」セクションをご覧ください。
<feature name="FeatureX">
<p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha">
<p>This can only be seen if variant 'Alpha' of 'FeatureX' is assigned.</p>
</feature>
また、ある機能や機能のセットが無効になっている場合に、タグ ヘルパーの評価を無効にしてコンテンツを表示することもできます。 以下の例で negate="true"
を設定することで、FeatureX
が無効な場合にのみコンテンツがレンダリングされます。
<feature negate="true" name="FeatureX">
<p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
<feature negate="true" name="FeatureX" variant="Alpha">
<p>This can only be seen if variant 'Alpha' of 'FeatureX' isn't assigned.</p>
</feature>
<feature>
タグは、name
/variant
属性でカンマ区切りの機能またはバリアントの一覧を指定することで、複数の機能またはバリアントを参照できます。
<feature name="FeatureX,FeatureY">
<p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha,Beta">
<p>This can only be seen if variant 'Alpha' or 'Beta' of 'FeatureX' is assigned.</p>
</feature>
Note
variant
を指定した場合、1 つの機能のみを指定する必要があります。
既定では、機能タグがレンダリングされるには、一覧表示されたすべての機能が有効になっている必要があります。 この動作は、以下の例のように requirement
属性を追加することでオーバーライドできます。
Note
And
の requirement
が variant
と一緒に使用されると、複数のバリアントを割り当てできないというエラーがスローされます。
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
<feature>
タグを使用するにはタグ ヘルパーが必要です。 これは、ViewImports.cshtml ファイルに機能管理タグ ヘルパーを追加することで実行できます。
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore
MVC フィルター
MVC アクション フィルターは、機能の状態に基づいて条件付きで実行するように設定できます。 これは、機能を意識した方法で MVC フィルターを登録することによって行われます。
機能管理パイプラインは、IAsyncActionFilter
を実装する非同期 MVC Action フィルターをサポートしています。
services.AddMvc(o =>
{
o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});
上記のコードは、SomeMvcFilter
という名前の MVC フィルターを追加します。 このフィルターは、 "FeatureX" が有効になっている場合のみ、MVC パイプライン内でトリガーされます。
Razor ページ
MVC Razor ページを実行するためには、指定した機能 (あるいは任意の機能リストのいずれか) を有効にする必要があります。 これは Microsoft.FeatureManagement.Mvc
名前空間にある FeatureGateAttribute
を使用することで実行できます。
[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
上記のコードでは、"FeatureX" を有効にする必要があるため Razor ページを設定しています。 この機能が有効でない場合、ページは HTTP 404 (NotFound) の結果を生成します。
Razor ページで使用する場合、FeatureGateAttribute
はページ ハンドラーの種類に配置する必要があります。 個別のハンドラー メソッドに配置することはできません。
アプリケーションの構築
機能管理ライブラリは、機能の状態に基づいて条件付きで実行されるアプリケーション分岐やミドルウェアを追加するために使用できます。
app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");
上記の呼び出しで、アプリケーションは、"FeatureX" 機能が有効な場合にのみ要求パイプラインに現れるミドルウェア コンポーネントを追加します。 実行中に機能を有効または無効にすると、ミドルウェア パイプラインを動的に変更できます。
以下は、機能に基づいてアプリケーション全体を分岐させる、より汎用的な機能を構築します。
app.UseForFeature(featureName, appBuilder =>
{
appBuilder.UseMiddleware<T>();
});
機能フィルターの実装
機能フィルターを作成すると、定義した条件に基づいて機能を有効にする方法を得られます。 機能フィルターを実装するには、IFeatureFilter
インターフェイスを実装する必要があります。 IFeatureFilter
には EvaluateAsync
という名前の単一のメソッドがあります。 機能が機能フィルターに対して有効であることを指定すると、EvaluateAsync
メソッドが呼び出されます。 EvaluateAsync
が true
を返す場合は、機能が有効になっていることを意味します。
次のスニペットは、カスタマイズされた機能フィルター MyCriteriaFilter
を追加する方法を示しています。
services.AddFeatureManagement()
.AddFeatureFilter<MyCriteriaFilter>();
機能フィルターは AddFeatureManagement
から返された IFeatureManagementBuilder
で AddFeatureFilter<T>
を呼び出すことで登録されます。 これらの機能フィルターは、機能フラグを追加するために使用されたサービス コレクション内に存在するサービスにアクセスできます。 依存関係の挿入は、これらのサービスを取得するために使用できます。
Note
フィルターが機能フラグ設定 (appsettings.json など) で参照される場合、型名の Filter 部分は省略する必要があります。 詳細については、「Filter Alias Attribute
」のセクションを参照してください。
パラメーター化された機能フィルター
一部の機能フィルターでは、機能をオンにするかどうかを決定するためのパラメーターが必要です。 たとえば、ブラウザー機能フィルターでは、特定のブラウザー セットの機能を有効にすることができます。 Edge およびChrome ブラウザーでは機能を有効にできますが、Firefox ではできません。 これを行うために、パラメーターを予測する機能フィルターを設計できます。 これらのパラメーターは機能構成で指定され、IFeatureFilter.EvaluateAsync
の FeatureFilterEvaluationContext
パラメーターを介してコードにアクセスできるようになります。
public class FeatureFilterEvaluationContext
{
/// <summary>
/// The name of the feature being evaluated.
/// </summary>
public string FeatureName { get; set; }
/// <summary>
/// The settings provided for the feature filter to use when evaluating whether the feature should be enabled.
/// </summary>
public IConfiguration Parameters { get; set; }
}
FeatureFilterEvaluationContext
には Parameters
という名前のプロパティがあります。 これらのパラメーターは、機能フィルターが機能を有効にする必要があるか評価する方法を決定するために使用できる生の構成を表します。 ブラウザー機能フィルターをもう一度例として使用するために、フィルターは機能用に指定される許可されたブラウザーのセットを抽出し、要求がそれらのブラウザーのどれかから送信されているか確認するために Parameters
を使用できます。
[FilterAlias("Browser")]
public class BrowserFilter : IFeatureFilter
{
…
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
{
BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();
//
// Here we would use the settings and see if the request was sent from any of BrowserFilterSettings.AllowedBrowsers
}
}
フィルター Alias 属性
機能フラグ用に機能フィルターが登録されている場合、構成で使用されるエイリアスは、Filter サフィックスがある場合は、それを取り除いた機能フィルターの種類の名前になります。 たとえば、MyCriteriaFilter
は構成では MyCriteria と呼ばれます。
"MyFeature": {
"EnabledFor": [
{
"Name": "MyCriteria"
}
]
}
これをオーバーライドするには、FilterAliasAttribute
を使用します。 機能フィルターをこの属性で装飾することで、機能フラグ内でこの機能フィルターを参照するために構成で使用する必要がある名前を宣言できます。
欠落した機能フィルター
機能が特定の機能フィルターに対して有効になるように構成されていて、その機能フィルターが登録されていない場合、機能の評価時に例外がスローされます。 例外は、機能管理オプションを使用して無効にすることができます。
services.Configure<FeatureManagementOptions>(options =>
{
options.IgnoreMissingFeatureFilters = true;
});
HttpContext の使用
機能フィルターは、HTTP 要求のプロパティに基づいて機能を有効にする必要があるか評価できます。 これは HTTP コンテキストを検査することで実行されます。 機能フィルターは、依存関係の挿入を通じて IHttpContextAccessor
を取得することで、HTTP コンテキストへの参照を取得できます。
public class BrowserFilter : IFeatureFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public BrowserFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
}
IHttpContextAccessor
を使用できるようにするには、起動時に依存関係の挿入コンテナーに追加する必要があります。 次の方法で IServiceCollection
に登録できます。
public void ConfigureServices(IServiceCollection services)
{
…
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
…
}
詳細設定: IHttpContextAccessor
/HttpContext
はサーバー側の Blazor アプリの Razor コンポーネントでは使用しないでください。 Blazor アプリで HTTP コンテキストを渡すために推奨されるアプローチは、データを範囲指定されたサービスにコピーすることです。 Blazor アプリの場合、AddScopedFeatureManagement
を使用して機能管理サービスを登録する必要があります。 詳細については、「Scoped Feature Management Services
」のセクションを参照してください。
機能評価のためのコンテキストの提供
コンソール アプリケーションには、機能フィルターで機能がオンかオフかを確認するために取得して利用できる HttpContext
のような環境コンテキストはありません。 この場合、アプリケーションは、機能フィルターで使用するために、コンテキストを表すオブジェクトを機能管理システムに提供する必要があります。 これは、IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext)
を使用して行います。 機能マネージャーに提供される appContext オブジェクトは、機能の状態を評価するために機能フィルターで使用できます。
MyAppContext context = new MyAppContext
{
AccountId = current.Id;
}
if (await featureManager.IsEnabledAsync(feature, context))
{
…
}
コンテキスト機能フィルター
コンテキスト機能フィルターは IContextualFeatureFilter<TContext>
インターフェイスを実装します。 これらの特殊な機能フィルターはIFeatureManager.IsEnabledAsync<TContext>
が呼び出されたときに渡されるコンテキストを活用できます。 IContextualFeatureFilter<TContext>
の TContext
型パラメーターは、フィルターで処理できるコンテキストの種類を記述します。 これにより、コンテキスト機能フィルターの開発者は、それを利用したいユーザーのために必要な内容を記述できます。 すべての種類はオブジェクトの子孫であるため、IContextualFeatureFilter<object>
を実装するフィルターは、提供された任意のコンテキストに対して呼び出すことができます。 より具体的なコンテキスト機能フィルターの例として、構成された有効なアカウントの一覧にアカウントがある場合に有効になる機能を考慮してください。
public interface IAccountContext
{
string AccountId { get; set; }
}
[FilterAlias("AccountId")]
class AccountIdFilter : IContextualFeatureFilter<IAccountContext>
{
public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountId)
{
//
// Evaluate if the feature should be on with the help of the provided IAccountContext
}
}
AccountIdFilter
では、機能の状態を評価できるようにするために提供される IAccountContext
を実装するオブジェクトが必要であることがわかります。 この機能フィルターを使用する場合、呼び出し元は IAccountContext
を実装するオブジェクトで渡されることを確認する必要があります。
Note
1 つの種類を実装できるのは、1 つの機能フィルター インターフェイスのみです。 複数の機能フィルター インターフェイスを実装する機能フィルターを追加しようとすると、ArgumentException
が生成されます。
同じエイリアスを使用するコンテキスト フィルターと非コンテキスト フィルターの使用
IFeatureFilter
と IContextualFeatureFilter
のフィルターは同じエイリアスを共有できます。 具体的には、ContextType
に適用可能なフィルターが最大 1 つある限り、0 または 1 個の IFeatureFilter
と 0 または N 個の IContextualFeatureFilter<ContextType>
で共有される 1 つのフィルター エイリアスを持つことができます。
次の文章では、アプリケーションに同じ名前のコンテキスト フィルターと非コンテキスト フィルターが登録されている場合の、フィルターの選択プロセスについて説明します。
FilterA
という非コンテキスト フィルターと、2 つのコンテキスト フィルター FilterB
と、それぞれ TypeB
および TypeC
コンテキストを承諾する FilterC があるとします。 3 つのフィルターはすべて同じエイリアス SharedFilterName
を共有します。
また、構成で機能フィルター SharedFilterName
を使用する機能フラグ MyFeature
もあります。
3 つのフィルターがすべて登録されている場合:
- IsEnabledAsync("MyFeature") を呼び出すと、
FilterA
が機能フラグを評価するために使用されます。 - IsEnabledAsync("MyFeature"、コンテキスト) を呼び出すと、コンテキストの種類が
TypeB
の場合はFilterB
が使用されます。 コンテキストの種類がTypeC
の場合はFilterC
が使用されます。 - IsEnabledAsync("MyFeature"、コンテキスト) を呼び出すと、コンテキストの種類が
TypeF
の場合はFilterA
が使用されます。
組み込み機能フィルター
Microsoft.FeatureManagement
パッケージには、PercentageFilter
、TimeWindowFilter
、ContextualTargetingFilter
、TargetingFilter
などのいくつかの機能フィルターがあります。 TargetingFilter
以外のすべてのフィルターは、AddFeatureManagement
メソッドで機能管理が登録されると自動的に追加されます。 TargetingFilter
は、以下の Targeting
セクションで詳述する WithTargeting
メソッドを使用して追加されます。
組み込み機能フィルターにはそれぞれ独自のパラメーターがあります。 こちらは、機能フィルターの一覧と例です。
Microsoft.Percentage
このフィルターは、設定された割合に基づいて機能を有効にする機能を提供します。
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.Percentage",
"Parameters": {
"Value": 50
}
}
]
}
Microsoft.TimeWindow
このフィルターは、時間枠に基づいて機能を有効にする機能を提供します。 End
のみ指定された場合、その時間までその機能はオンとみなされます。 Start
のみ指定された場合、その時点以降のすべての時点で機能はオンとみなされます。
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.TimeWindow",
"Parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
}
時間枠は定期的に反復するように構成できます。 これは、トラフィックの少ない時間帯や多い時間帯、あるいは特定の曜日に機能をオンにする必要があるシナリオに役立ちます。 個別の時間枠を反復する時間枠に拡張するには、Recurrence
パラメーターで繰り返し規則を指定する必要があります。
Note
Recurrence
を有効にするには、Start
と End
の両方を指定する必要があります。
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.TimeWindow",
"Parameters": {
"Start": "Fri, 22 Mar 2024 20:00:00 GMT",
"End": "Sat, 23 Mar 2024 02:00:00 GMT",
"Recurrence": {
"Pattern": {
"Type": "Daily",
"Interval": 1
},
"Range": {
"Type": "NoEnd"
}
}
}
}
]
}
Recurrence
設定は、Pattern
(時間枠を繰り返す頻度) と Range
(繰り返しパターンを繰り返す期間) の 2 つの部分で構成されています。
定期的なパターン
繰り返しパターンには、Daily
と Weekly
の 2 種類があります。 たとえば、"毎日"、"3 日ごと"、"毎週月曜日"、"毎週金曜日以外" などの時間枠を繰り返すことができます。
種類によって、Pattern
の特定のフィールドは必須、任意、または無視されます。
Daily
日単位の繰り返しパターンでは、それぞれ発生した日の日数に基づいて時間枠が繰り返されます。
プロパティ 関連性 説明 Type 必須 Daily
に設定する必要があります。間隔 省略可能 それぞれ発生した日の日数で指定します。 既定値は 1 です。 Weekly
週単位の繰り返しパターンでは、それぞれ発生した週の週数に基づいて、時間枠が同じ日または曜日に繰り返されます。
プロパティ 関連性 説明 Type 必須 Weekly
に設定する必要があります。DaysOfWeek 必須 イベントが発生する曜日を指定します。 間隔 省略可能 それぞれ発生した週の週数で指定します。 既定値は 1 です。 FirstDayOfWeek 省略可能 どの曜日を週の初日とみなすかを指定します。 既定値は Sunday
。次の例は、隔週の月曜日と火曜日に時間枠を繰り返します。
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Note
Start
は、繰り返しパターンに当てはまる有効な最初の発生である必要があります。 さらに、時間枠の期間は、それが発生する頻度よりも長くすることはできません。 たとえば、毎日 25 時間の時間枠の繰り返しは無効です。
定期実行範囲
使用可能な繰り返しの範囲の種類は、NoEnd
、EndDate
、Numbered
の 3 つがあります。
NoEnd
NoEnd
の範囲では、繰り返しが無期限に発生します。プロパティ 関連性 説明 Type 必須 NoEnd
に設定する必要があります。EndDate
EndDate
の範囲は、終了日まで該当するパターンに当てはまるすべての日に発生するように時間枠に影響します。プロパティ 関連性 説明 Type 必須 EndDate
に設定する必要があります。EndDate 必須 パターンの適用を停止する日付と時刻を指定します。 最後の発生日の開始時刻が終了日より前である限り、その発生日の終了時刻はその時間を超えて延長できます。 次の例では、2024 年 4 月 1 日に最後に発生するまで、毎日時間枠を繰り返します。
"Start": "Fri, 22 Mar 2024 18:00:00 GMT", "End": "Fri, 22 Mar 2024 20:00:00 GMT", "Recurrence":{ "Pattern": { "Type": "Daily", "Interval": 1 }, "Range": { "Type": "EndDate", "EndDate": "Mon, 1 Apr 2024 20:00:00 GMT" } }
Numbered
Numbered
の範囲では、時間枠が (パターンに基づいて) 決まった回数発生します。プロパティ 関連性 説明 Type 必須 Numbered
に設定する必要があります。NumberOfOccurrences 必須 発生回数を指定します。 次の例では、月曜日と火曜日に時間枠を繰り返し、4 月 1 日 (月)、4 月 2 日 (火)、4 月 8 日 (月) の 3 回発生します。
"Start": "Mon, 1 Apr 2024 18:00:00 GMT", "End": "Mon, 1 Apr 2024 20:00:00 GMT", "Recurrence":{ "Pattern": { "Type": "Weekly", "Interval": 1, "DaysOfWeek": ["Monday", "Tuesday"] }, "Range": { "Type": "Numbered", "NumberOfOccurrences": 3 } }
繰り返し規則を作成するには、Pattern
と Range
の両方を指定する必要があります。 どのパターンの種類でも、どの範囲の種類でも機能します。
詳細: Start
プロパティのタイム ゾーン オフセットが繰り返し設定に適用されます。
Microsoft.Targeting
このフィルターは、対象ユーザーに対して機能を有効にする機能を提供します。 対象設定の詳細については、以下の「対象設定」セクションで説明します。 フィルター パラメーターには、ユーザー、グループ、除外ユーザー/グループ、およびその機能にアクセスできるユーザーベースの既定の割合を記述する Audience
オブジェクトが含まれます。 Groups
セクションに一覧表示されている各グループ オブジェクトは、グループのメンバーの何パーセントがアクセスできるかも指定する必要があります。 ユーザーがExclusion
セクションで指定されている場合、そのユーザーが直接指定されている場合、またはそのユーザーが除外されているグループに属している場合に、機能は無効になります。 それ以外の場合、Users
セクションでユーザーが直接指定された場合、またはユーザーがいずれかのグループ ロールアウトの割合に含まれる場合、またはユーザーが既定ロールアウトの割合に含まれる場合、そのユーザーの機能が有効になります。
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.Targeting",
"Parameters": {
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
},
{
"Name": "Ring1",
"RolloutPercentage": 50
}
],
"DefaultRolloutPercentage": 20,
"Exclusion": {
"Users": [
"Ross"
],
"Groups": [
"Ring2"
]
}
}
}
}
]
}
機能フィルター Alias 名前空間
すべての組み込み機能フィルターのエイリアスは Microsoft
機能フィルター名前空間にあります。 これは、同じエイリアスを共有する可能性のある他の機能フィルターとの競合を防ぐためです。 機能フィルターの名前空間のセグメントは、'.' 文字で分割されます。 機能フィルターは、Microsoft.Percentage
などの完全修飾されたエイリアス、または Microsoft.Percentage
が Percentage
である場合は最後のセグメントで参照できます。
ターゲティング
対象設定は、開発者が新しい機能をユーザー ベースに段階的にロールアウトできるようにする機能管理戦略です。 この戦略は、対象ユーザーと呼ばれる一連のユーザーを対象設定するという概念に基づいて構築されています。 対象ユーザーは、特定のユーザー、グループ、除外されたユーザー/グループ、およびユーザー ベース全体の指定された割合で構成されます。 対象ユーザーに含まれるグループは、メンバーの合計数に対する割合にさらに分けることができます。
次の手順は、新しい「ベータ」機能の段階的なロールアウトの例を示しています。
- 個人ユーザーの Jeff と Alicia にベータ版へのアクセス権が付与されます
- もう 1 人のユーザー Mark はオプトインを要求し、オプトインされます。
- 「Ring1」ユーザーと呼ばれるグループの 20% がベータ版に含まれています。
- ベータ版に含まれる「Ring1」ユーザーの数は、最大 100% 増加します。
- ユーザー ベースの 5% がベータに含まれています。
- ロールアウト率は最大 100% まで増加し、機能は完全にロールアウトされます。
機能をロールアウトするこの戦略では、これに含まれる Microsoft.Targeting 機能フィルターを通してライブラリに組み込まれています。
Web アプリケーションでの対象設定
対象設定機能フィルターを使用する Web アプリケーションの例は FeatureFlagDemo のプロジェクトの例にあります。
アプリケーションで TargetingFilter
の使用を開始するには、他の機能フィルターと同様にアプリケーションのサービス コレクションに追加する必要があります。 他の組み込みフィルターとは異なり、TargetingFilter
はアプリケーションのサービス コレクションに追加される別のサービスに依存します。 そのサービスは ITargetingContextAccessor
です。
Microsoft.FeatureManagement.AspNetCore
には、要求の HttpContext
からターゲット設定情報を抽出する ITargetingContextAccessor
の既定の実装が用意されています。 IFeatureManagementBuilder
に対して非ジェネリック WithTargeting
オーバーロードを使用してターゲット設定を指定するときに、既定のターゲット設定コンテキスト アクセサーを使用できます。
既定の対象設定コンテキスト アクセサーと TargetingFilter
は、IFeatureManagementBuilder
で WithTargeting
を呼び出すことで登録されます。
services.AddFeatureManagement()
.WithTargeting();
WithTargeting<T>
を呼び出して、ITargetingContextAccessor
と TargetingFilter
のカスタマイズされた実装を登録することもできます。 ExampleTargetingContextAccessor
と呼ばれる ITargetingContextAccessor
を実装した TargetingFilter
を使用するために、Web アプリケーションで機能管理を設定する例をこちらに示します。
services.AddFeatureManagement()
.WithTargeting<ExampleTargetingContextAccessor>();
ITargetingContextAccessor
Web アプリケーションで TargetingFilter
を使用するには、ITargetingContextAccessor
の実装が必要です。 これは、対象設定評価を行う場合に、現時点でどのユーザーを評価しているかなどのコンテキスト情報が必要になるためです。 この情報は TargetingContext
と呼ばれます。 アプリケーションによって、この情報を抽出する場合が異なる場合があります。 アプリケーションが対象設定コンテキストを取得する一般的な例として、要求の HTTP コンテキストやデータベースがあります。
アプリケーションの HTTP コンテキストからターゲット設定コンテキスト情報を抽出する例は、Microsoft.FeatureManagement.AspNetCore
パッケージが提供する DefaultHttpTargetingContextAccessor
です。 これを使って HttpContext.User
からターゲット設定情報を抽出します。 UserId
情報は Identity.Name
フィールドから抽出され、Groups
情報は種類 Role
の要求から抽出されます。 この実装は、ここで説明されている IHttpContextAccessor
の使用に依存しています。
コンソール アプリケーションの対象設定
対象設定フィルターは、機能をオンにする必要があるか評価するために、ターゲット設定コンテキストに依存します。 この対象設定コンテキストには、現時点でどのユーザーが評価されているか、どのグループに属しているかなどの情報が含まれています。 コンソール アプリケーションでは、通常、この情報を対象設定フィルターに流すための環境コンテキストはありません。したがって、FeatureManager.IsEnabledAsync
が呼び出される場合に渡す必要があります。 これは ContextualTargetingFilter
を使用することでサポートされます。 対象設定コンテキストを機能マネージャーに流す必要があるアプリケーションは、TargetingFilter.
の代わりにこれを使用する必要があります。
ContextualTargetingFilter
は IContextualTargetingFilter<ITargetingContext>
であるため、ITargetingContext
の実装を IFeatureManager.IsEnabledAsync
に渡して、その機能を評価してオンにできるようにする必要があります。
IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
UserId = userId,
Groups = groups
};
await fm.IsEnabledAsync(featureName, targetingContext);
ContextualTargetingFilter
は引き続き機能フィルターのエイリアス Microsoft.Targeting を使用しているため、このフィルターの構成はそのセクションで参照されている内容と一致しています。
コンソール アプリケーションで ContextualTargetingFilter
を使用する例は TargetingConsoleApp プロジェクトの例にあります。
対象設定評価オプション
すべての機能に対象設定評価を実行する方法をカスタマイズするオプションが用意されています。 これらのオプションは、機能管理の設定時に構成できます。
services.Configure<TargetingEvaluationOptions>(options =>
{
options.IgnoreCase = true;
});
対象設定の除外
対象ユーザーを定義する場合、ユーザーやグループを対象ユーザーから除外できます。 これは、ある機能をユーザー グループにロールアウトする場合に、一部のユーザーまたはグループをロールアウトから除外する必要がある場合に役立ちます。 除外は、対象ユーザー Exclusion
プロパティにユーザーとグループの一覧を追加することで定義されます。
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
上記の例では、Jeff
と Alicia
という名前のユーザーに対してこの機能が有効になっています。 また、Ring0
という名前のグループのユーザーに対しても有効です。 ただし、ユーザーの名前が Mark
である場合、そのユーザーがグループ Ring0
に属しているかに関係なく、機能は無効になります。 除外は対象設定フィルターの残りの部分よりも優先されます。
バリアント
アプリケーションに新しい機能が追加される場合、その機能に複数の異なる設計オプションがある場合があります。 設計を決定するための一般的な解決策は、一種の A/B テストです。これは、ユーザー ベースの異なるセグメントに機能の異なるバージョンを提供し、ユーザー操作に基づいてバージョンを選択するものです。 このライブラリでは、機能のさまざまな構成をバリアントで表現することで、この機能が有効になります。
バリアントは、機能フラグを単なるオン/オフのフラグ以上のものにします。 バリアントは機能フラグの値を表し、文字列、数値、ブール値、あるいは構成オブジェクトである場合もあります。 バリアントを宣言する機能フラグは、それぞれのバリアントをどのような状況で使用する必要があるかを定義する必要があります。この詳細については、「バリアントの割り当て」セクションで扱っています。
public class Variant
{
/// <summary>
/// The name of the variant.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The configuration of the variant.
/// </summary>
public IConfigurationSection Configuration { get; set; }
}
バリアントの取得
各機能について、IVariantFeatureManager
の GetVariantAsync
メソッドを使用してバリアントを取得できます。
…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU, CancellationToken.None);
IConfigurationSection variantConfiguration = variant.Configuration;
// Do something with the resulting variant and its configuration
バリアントが取得されると、バリアントの設定はバリアントの Configuration
プロパティから IConfigurationSection
として直接使用できます。 もう 1 つのオプションは、.NET の構成バインド パターンを使用して、構成をオブジェクトにバインドすることです。
IConfigurationSection variantConfiguration = variant.Configuration;
MyFeatureSettings settings = new MyFeatureSettings();
variantConfiguration.Bind(settings);
返されるバリアントは現在評価されているユーザーに依存し、その情報は TargetingContext
のインスタンスから得られます。 このコンテキストは GetVariantAsync
を呼び出すときに渡すか、ITargetingContextAccessor
の実装が登録されている場合はそこから自動的に取得します。
バリアント機能フラグの宣言
通常の機能フラグと比較して、バリアント機能フラグには 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
プロパティは null になります。
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 機能フィルターと似ていますが、パラメーターには、ターゲット設定に存在するが割り当てに存在しないものや、その逆があります。 対象設定と割り当ての結果は関係ありません。
Note
機能バリアントを割り当てられるようにするには、ITargetingContextAccessor
を登録する必要があります。 これは WithTargeting<T>
メソッドを呼び出すことで実行できます。
バリアントを使用する有効な状態のオーバーライド
機能フラグの有効な状態をオーバーライドするためにバリアントを使用できます。 これにより、バリアントが機能フラグの評価を拡張する機会が付与されます。 バリアントのあるフラグに対して IsEnabled
を呼び出すと、機能マネージャーは、現在のユーザーに割り当てられているバリアントが結果をオーバーライドするように構成されているかどうかを調べます。 これは省略可能なバリアント プロパティ status_override
を使用して行われます。 既定では、このプロパティは None
に設定されており、バリアントはフラグが有効か無効であるかに影響しないことを意味します。 status_override
を Enabled
に設定すると、バリアントが選択されたときにフラグをオーバーライドして有効にすることができます。 status_override
を Disabled
に設定すると逆の機能が提供され、バリアントが選択されたときにフラグが無効になります。 enabled
状態が false
の機能はオーバーライドできません。
バイナリのバリアントで機能フラグを使用する場合、status_override
プロパティが非常に役立ちます。 これにより、アプリケーションで IsEnabledAsync
や FeatureGateAttribute
のような 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
と等しいため、その機能は無効とみなされます。
依存関係の挿入のバリアント
バリアント機能フラグは、依存関係の挿入と組み合わせて使用することで、ユーザーごとに異なるサービスの実装を表示できます。 これを行うには、IVariantServiceProvider<TService>
インターフェイスを使用します。
IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...
IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken);
上記のスニペットでは、IVariantServiceProvider<IAlgorithm>
は依存関係の挿入コンテナーから IAlgorithm
の実装を取得します。 選択された実装は、以下に依存します。
IAlgorithm
サービスが登録された機能フラグ。- その機能に割り当てられたバリアント。
IVariantServiceProvider<T>
は IFeatureManagementBuilder.WithVariantService<T>(string featureName)
を呼び出すことでアプリケーションに利用できるようになります。 例については、以下を参照してください。
services.AddFeatureManagement()
.WithVariantService<IAlgorithm>("ForecastAlgorithm");
上記の呼び出しは IVariantServiceProvider<IAlgorithm>
をサービス コレクションで利用できるようにします。 IAlgorithm
の実装は、services.AddSingleton<IAlgorithm, SomeImplementation>()
のような add メソッドを介して個別に追加する必要があります。 IVariantServiceProvider
で使用される IAlgorithm
の実装は ForecastAlgorithm
のバリアント機能フラグに依存します。 IAlgorithm
の実装がサービス コレクションに追加されていない場合、IVariantServiceProvider<IAlgorithm>.GetServiceAsync()
は null の結果を持つタスクを返します。
{
// The example variant feature flag
"id": "ForecastAlgorithm",
"enabled": true,
"variants": [
{
"Name": "AlgorithmBeta"
},
...
]
}
バリアント サービス Alias 属性
[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
...
}
バリアント サービス プロバイダーは割り当てられたバリアントに一致する実装の型名を使用します。 バリアント サービスが VariantServiceAliasAttribute
で装飾されている場合、この属性で宣言された名前は、このバリアント サービスを参照するために構成で使用する必要があります。
テレメトリ
機能フラグの変更がデプロイされると、多くの場合、アプリケーションへの影響の分析が重要です。 たとえば、可能性のある質問は次のとおりです。
- 私のフラグは期待どおりに有効または無効になっていますか?
- 対象ユーザーは、期待どおりに特定の機能にアクセスできていますか?
- どのバリアントが特定のユーザーに表示されていますか?
この種の質問には、機能フラグ評価イベントの生成と分析を通じて回答できます。 このライブラリでは、System.Diagnostics.Activity
API を使用して、機能フラグの評価中にトレース テレメトリを生成します。
テレメトリの有効化
既定では、機能フラグにはテレメトリがありません。 指定された機能フラグに対してテレメトリを発行するには、フラグはテレメトリ生成のために有効であることを宣言する必要があります。
appsettings.json
で定義された機能フラグの場合は、telemetry
プロパティを使用して行われます。
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
上記の appsettings スニペットでは、テレメトリを有効にする MyFeatureFlag
という名前の機能フラグを定義しています。 これは、enabled
を true に設定する telemetry
オブジェクトによって示されます。 フラグのテレメトリを発行するには、enabled
プロパティの値を true
にする必要があります。
機能フラグの telemetry
セクションには次のプロパティがあります。
プロパティ | 説明 |
---|---|
enabled |
機能フラグに対してテレメトリを発行するかどうかを指定します。 |
metadata |
機能フラグに関するカスタム メタデータを評価イベントにアタッチするために使用できる、辞書としてモデル化されたキーと値のペアのコレクション。 |
カスタム テレメトリの発行
機能マネージャーには、"Microsoft.FeatureManagement" という独自の ActivitySource
があります。 機能フラグに対して telemetry
が有効な場合、機能フラグの評価が開始されるたびに、機能マネージャーは Activity
を開始します。 機能フラグの評価が完了すると、機能マネージャーは FeatureFlag
という ActivityEvent
を現在のアクティビティに追加します。 FeatureFlag
イベントは、機能フラグ評価に関する情報を含むタグを持つことになり、これは FeatureEvaluationEvent スキーマ内で定義されているフィールドに従います。
Note
機能フラグの telemetry.metadata
で指定されたすべてのキーと値のペアもタグに含まれます。
カスタム テレメトリの発行を有効にするには、ActivityListener
を作成し、Microsoft.FeatureManagement
アクティビティ ソースをリッスンします。 次の例は、機能管理アクティビティ ソースをリッスンし、機能の評価時にコールバックを追加する方法を示しています。
ActivitySource.AddActivityListener(new ActivityListener()
{
ShouldListenTo = (activitySource) => activitySource.Name == "Microsoft.FeatureManagement",
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
ActivityStopped = (activity) =>
{
ActivityEvent? evaluationEvent = activity.Events.FirstOrDefault((activityEvent) => activityEvent.Name == "FeatureFlag");
if (evaluationEvent.HasValue && evaluationEvent.Value.Tags.Any())
{
// Do something.
}
}
});
詳細については、「分散トレースを収集する」を参照してください。
Application Insights のテレメトリ パブリッシャー
Microsoft.FeatureManagement.Telemetry.ApplicationInsights
パッケージには、Application Insights に機能フラグ評価データを送信する組み込みのテレメトリ パブリッシャーが用意されています。 これを活用するには、以下に示すようにパッケージに参照を追加し、Application Insights テレメトリ パブリッシャーを登録します。
builder.services
.AddFeatureManagement()
.AddApplicationInsightsTelemetryPublisher();
Microsoft.FeatureManagement.Telemetry.ApplicationInsights
パッケージには、イベントをフラグ評価にリンクできるように、すべてのイベントに自動的に TargetingId
のタグを付けるテレメトリ初期化子が用意されています。 テレメトリ初期化子 TargetingTelemetryInitializer
を使用するには、それをアプリケーションのサービス コレクションに追加します。
builder.Services.AddSingleton<ITelemetryInitializer, TargetingTelemetryInitializer>();
Note
TargetingTelemetryInitializer
が期待どおりに機能するようにするには、以下で説明する TargetingHttpContextMiddleware
を使用する必要があります。
現在のアクティビティでターゲット設定コンテキストの永続化を有効にするには、TargetingHttpContextMiddleware
を使用できます。
app.UseMiddleware<TargetingHttpContextMiddleware>();
この使用方法の例は、VariantAndTelemetryDemo の例にあります。
前提条件
このテレメトリ パブリッシャーは、Application Insights が既に設定され、アプリケーション サービスとして登録されていることに依存します。 たとえば、これはアプリケーションの例のこちらで行われています。
このテレメトリ パブリッシャーは、Application Insights が既に設定され、アプリケーション サービスとして登録されていることに依存します。
キャッシュ
機能の状態は IConfiguration
システムによって提供されます。 キャッシュや動的な更新は、構成プロバイダーによって処理されることが期待されています。 機能マネージャーは、機能が有効であると確認されるたびに、IConfiguration
に機能の状態の最新の値を要求します。
スナップショット
要求の有効期間中、機能の状態が一貫性を維持することが必要なシナリオがあります。 標準の IFeatureManager
から返される値は、要求中に IConfiguration
ソースが更新された場合に変更される可能性があります。 これは、IFeatureManagerSnapshot
を使用することで防ぐことができます。 IFeatureManagerSnapshot
は、IFeatureManager
と同じ方法で取得できます。 IFeatureManagerSnapshot
は IFeatureManager
のインターフェイスを実装していますが、要求中に機能の最初に評価された状態をキャッシュし、有効期間中に機能の同じ状態を返します。
カスタム機能プロバイダー
カスタム機能プロバイダーを実装すると、開発者はデータベースや機能管理サービスなどのソースから機能フラグをプルできます。 既定で使用される機能プロバイダーは、.NET Core の構成システムから機能フラグをプルします。 これにより、appsettings.json ファイルまたは Azure App Configuration のような構成プロバイダーで機能を定義できます。 この動作に置き換えることで、機能の定義の読み込み元を完全に制御できます。
機能の定義の読み込みをカスタマイズするには、IFeatureDefinitionProvider
インターフェイスを実装する必要があります。
public interface IFeatureDefinitionProvider
{
Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);
IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}
IFeatureDefinitionProvider
の実装を使用するには、機能管理を追加する前にサービス コレクションに追加する必要があります。 次の例では、InMemoryFeatureDefinitionProvider
という名前の IFeatureDefinitionProvider
の実装を追加しています。
services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
.AddFeatureManagement()
次のステップ
アプリケーションで機能フラグを使用する方法については、次のクイックスタートに進んでください。
機能フィルターの使用方法について学ぶには、次のチュートリアルに進んでください。