Zarządzanie funkcjami platformy .NET
Biblioteka zarządzania funkcjami platformy .NET umożliwia opracowywanie i uwidacznianie funkcjonalności aplikacji na podstawie flag funkcji. Po utworzeniu nowej funkcji wiele aplikacji ma specjalne wymagania, takie jak włączenie funkcji i określenie warunków. Ta biblioteka umożliwia zdefiniowanie tych relacji, a także integruje się z typowymi wzorcami kodu platformy .NET, aby uwidocznić te funkcje.
Flagi funkcji umożliwiają aplikacjom platformy .NET i ASP.NET Core dynamiczne włączanie lub wyłączanie funkcji. Deweloperzy mogą używać flag funkcji w prostych przypadkach użycia, takich jak instrukcje warunkowe, do bardziej zaawansowanych scenariuszy, takich jak warunkowe dodawanie tras lub filtrów MVC. Flagi funkcji są oparte na systemie konfiguracji platformy .NET Core. Każdy dostawca konfiguracji platformy .NET Core może działać jako szkielet flag funkcji.
Poniżej przedstawiono niektóre korzyści wynikające z używania biblioteki zarządzania funkcjami platformy .NET:
Wspólna konwencja zarządzania funkcjami
Niski poziom bariery do wejścia
- Zbudowany na
IConfiguration
- Obsługuje konfigurację flagi funkcji pliku JSON
- Zbudowany na
Zarządzanie okresem istnienia flagi funkcji
- Wartości konfiguracji mogą ulec zmianie w czasie rzeczywistym; flagi funkcji mogą być spójne w całym żądaniu
Scenariusze proste i złożone
- Przełączanie/wyłączanie funkcji za pomocą deklaratywnego pliku konfiguracji
- Dynamiczne ocenianie stanu funkcji na podstawie wywołania do serwera
Rozszerzenia interfejsu API dla platformy ASP.NET Core i MVC
- Routing
- Filtry
- Atrybuty akcji
Biblioteka zarządzania funkcjami platformy .NET jest typu open source. Aby uzyskać więcej informacji, odwiedź repozytorium GitHub.
Flagi funkcji
Flagi funkcji składają się z dwóch części, nazwy i listy filtrów funkcji, które są używane do włączania funkcji.
Filtry funkcji
Filtry funkcji definiują scenariusz włączania funkcji. Gdy funkcja jest oceniana pod kątem tego, czy jest włączona, czy wyłączona, jej lista filtrów funkcji jest przechodzina do momentu, aż jeden z filtrów zdecyduje, że funkcja powinna zostać włączona. W tym momencie funkcja jest uznawana za włączoną i przechodzi przez filtry funkcji. Jeśli żaden filtr funkcji nie wskazuje, że funkcja powinna być włączona, jest uważana za wyłączoną.
Na przykład można zaprojektować filtr funkcji przeglądarki Microsoft Edge. Ten filtr funkcji aktywuje wszystkie funkcje, do których jest dołączony, o ile żądanie HTTP pochodzi z przeglądarki Microsoft Edge.
Konfiguracja flagi funkcji
System konfiguracji platformy .NET Core służy do określania stanu flag funkcji. Podstawą tego systemu jest IConfiguration
. Dowolny dostawca IConfiguration
dla programu może służyć jako dostawca stanu funkcji dla biblioteki flag funkcji. Ten system umożliwia scenariusze od appsettings.json do aplikacja systemu Azure Konfiguracji i nie tylko.
Deklaracja flagi funkcji
Biblioteka zarządzania funkcjami obsługuje appsettings.json jako źródło flagi funkcji, ponieważ jest to dostawca systemu .NET Core IConfiguration
. Poniżej przedstawiono przykład formatu używanego do konfigurowania flag funkcji w pliku 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"
}
}
]
}
}
}
Sekcja FeatureManagement
dokumentu JSON jest używana przez konwencję do ładowania ustawień flag funkcji. W powyższej sekcji przedstawiono trzy różne funkcje. Funkcje definiują filtry funkcji przy użyciu EnabledFor
właściwości . W filtrach funkcji dla FeatureT
elementu widzimy wartość AlwaysOn
. Ten filtr funkcji jest wbudowany i jeśli zostanie określony, zawsze włączy tę funkcję. Filtr AlwaysOn
funkcji nie wymaga żadnej konfiguracji, dlatego ma Name
tylko właściwość . FeatureU
nie ma filtrów we właściwości i w związku z tym EnabledFor
nigdy nie zostanie włączony. Wszystkie funkcje, które opierają się na tej włączonej funkcji, nie będą dostępne tak długo, jak filtry funkcji pozostaną puste. Jednak po dodaniu filtru funkcji, który umożliwia rozpoczęcie pracy funkcji. FeatureV
określa filtr funkcji o nazwie TimeWindow
. Jest to przykład konfigurowalnego filtru funkcji. W przykładzie widać, że filtr ma Parameters
właściwość . Służy do konfigurowania filtru. W takim przypadku konfigurowane są czasy rozpoczęcia i zakończenia dla funkcji, która ma być aktywna.
Szczegółowy schemat FeatureManagement
sekcji można znaleźć tutaj.
Zaawansowane: użycie dwukropka ":" jest zabronione w nazwach flag funkcji.
Deklaracja wł./wył.
Poniższy fragment kodu przedstawia alternatywny sposób definiowania funkcji, która może służyć do włączania/wyłączania funkcji.
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in config file
"FeatureManagement": {
"FeatureT": true, // On feature
"FeatureX": false // Off feature
}
}
Typ wymagania
Właściwość RequirementType
flagi funkcji służy do określania, czy filtry powinny być używane Any
, czy All
logika podczas oceniania stanu funkcji. Jeśli RequirementType
nie zostanie określony, wartość domyślna to Any
.
Any
oznacza, że tylko jeden filtr musi mieć wartość true, aby funkcja została włączona.All
oznacza, że każdy filtr musi mieć wartość true, aby funkcja została włączona.
A RequirementType
zmiany All
przechodzenia. Po pierwsze, jeśli nie ma filtrów, funkcja jest wyłączona. Następnie filtry funkcji są przechodzine do momentu, aż jeden z filtrów zdecyduje, że funkcja powinna zostać wyłączona. Jeśli żaden filtr nie wskazuje, że funkcja powinna być wyłączona, jest uważana za włączoną.
"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"
}
}
]
}
W powyższym przykładzie określa wartość RequirementType
All
, co oznacza, FeatureW
że wszystkie jego filtry muszą mieć wartość true, aby funkcja została włączona. W takim przypadku funkcja jest włączona dla 50% użytkowników w określonym przedziale czasu.
Schemat zarządzania funkcjami firmy Microsoft
Biblioteka zarządzania funkcjami obsługuje również użycie Microsoft Feature Management schema
funkcji do deklarowania flag funkcji. Ten schemat jest niezależny od języka pochodzenia i jest obsługiwany przez wszystkie biblioteki zarządzania funkcjami firmy 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"
}
}
]
}
}
]
}
}
Uwaga
Jeśli sekcję feature_management
można znaleźć w konfiguracji, FeatureManagement
sekcja zostanie zignorowana.
Biblioteka zarządzania funkcjami obsługuje appsettings.json jako źródło flagi funkcji, ponieważ jest to dostawca systemu .NET Core IConfiguration
. Flagi funkcji są deklarowane przy użyciu elementu Microsoft Feature Management schema
. Ten schemat jest niezależny od języka pochodzenia i jest obsługiwany przez wszystkie biblioteki zarządzania funkcjami firmy Microsoft.
Poniżej przedstawiono przykład deklarowania flag funkcji w pliku 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"
}
}
]
}
}
]
}
}
Sekcja feature_management
dokumentu JSON jest używana przez konwencję do ładowania ustawień flag funkcji. Obiekty flag funkcji muszą być wymienione w tablicy feature_flags
w feature_management
sekcji . W powyższej sekcji widzimy, że udostępniliśmy trzy różne funkcje. Flaga funkcji ma id
właściwości i enabled
. To id
nazwa używana do identyfikowania i odwołowania się do flagi funkcji. Właściwość enabled
określa stan włączonej flagi funkcji. Funkcja jest wyłączona , jeśli enabled
ma wartość false. Jeśli enabled
wartość ma wartość true, stan funkcji zależy od conditions
wartości . Jeśli nie ma conditions
, funkcja jest włączona. Jeśli istnieją conditions
i są one spełnione, funkcja jest włączona. Jeśli istnieją conditions
i nie są one spełnione, funkcja jest wyłączona. Właściwość conditions
deklaruje warunki używane do dynamicznego włączania funkcji. Funkcje definiują filtry funkcji w tablicy client_filters
. FeatureV
określa filtr funkcji o nazwie Microsoft.TimeWindow
. Jest to przykład konfigurowalnego filtru funkcji. W przykładzie widać, że filtr ma Parameters
właściwość . Służy do konfigurowania filtru. W takim przypadku konfigurowane są czasy rozpoczęcia i zakończenia dla funkcji, która ma być aktywna.
Zaawansowane: użycie dwukropka ":" jest zabronione w nazwach flag funkcji.
Typ wymagania
Właściwość requirement_type
elementu conditions
służy do określania, czy filtry powinny być używane Any
, czy All
logika podczas oceniania stanu funkcji. Jeśli requirement_type
nie zostanie określony, wartość domyślna to Any
.
Any
oznacza, że tylko jeden filtr musi mieć wartość true, aby funkcja została włączona.All
oznacza, że każdy filtr musi mieć wartość true, aby funkcja została włączona.
A requirement_type
zmiany All
przechodzenia. Najpierw, jeśli nie ma filtru, funkcja zostanie wyłączona. Jeśli istnieją filtry, filtry funkcji są przechodzine do momentu, aż jeden z filtrów zdecyduje, że funkcja powinna zostać wyłączona. Jeśli żaden filtr nie wskazuje, że funkcja powinna być wyłączona, zostanie ona uznana za włączoną.
{
"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"
}
}
]
}
}
W powyższym przykładzie określa wartość requirement_type
All
, co oznacza, FeatureW
że wszystkie jego filtry muszą mieć wartość true, aby funkcja została włączona. W takim przypadku funkcja zostanie włączona dla 50% użytkowników w określonym przedziale czasu.
Schemat zarządzania funkcjami platformy .NET
W poprzednich wersjach podstawowym schematem biblioteki zarządzania funkcjami była .NET feature management schema
. Począwszy od wersji 4.0.0, nowe funkcje, w tym warianty i dane telemetryczne, nie będą obsługiwane dla schematu zarządzania funkcjami platformy .NET.
Uwaga
Jeśli w sekcjach i FeatureManagement
znajduje się feature_management
deklaracja flagi funkcji, zostanie przyjęta ta z feature_management
sekcji .
Zużycie
Podstawową formą zarządzania funkcjami jest sprawdzenie, czy flaga funkcji jest włączona, a następnie wykonuje akcje na podstawie wyniku. Odbywa się to za pomocą IFeatureManager
metody "s IsEnabledAsync
".
…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
// Do something
}
Rejestracja usługi
Zarządzanie funkcjami opiera się na iniekcji zależności platformy .NET Core. Usługi zarządzania funkcjami można zarejestrować przy użyciu standardowych konwencji.
using Microsoft.FeatureManagement;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
}
}
Domyślnie menedżer funkcji pobiera konfigurację flagi funkcji z sekcji "FeatureManagement" danych konfiguracji platformy .NET Core. Jeśli sekcja "FeatureManagement" nie istnieje, konfiguracja jest uważana za pustą.
Uwaga
Można również określić, że konfiguracja flagi funkcji powinna zostać pobrana z innej sekcji konfiguracji, przekazując sekcję do AddFeatureManagement
. Poniższy przykład informuje menedżera funkcji o konieczności odczytania z innej sekcji o nazwie "MyFeatureFlags":
services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));
Wstrzykiwanie zależności
W przypadku korzystania z biblioteki zarządzania funkcjami w programie MVC IFeatureManager
można uzyskać za pomocą wstrzykiwania zależności.
public class HomeController : Controller
{
private readonly IFeatureManager _featureManager;
public HomeController(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
}
Usługi zarządzania funkcjami w zakresie
Metoda AddFeatureManagement
dodaje usługi zarządzania funkcjami jako pojedynczetony w aplikacji, ale istnieją scenariusze, w których może być konieczne dodanie usług zarządzania funkcjami jako usług o określonym zakresie. Na przykład użytkownicy mogą chcieć używać filtrów funkcji korzystających z usług o określonym zakresie na potrzeby informacji kontekstowych. W takim przypadku AddScopedFeatureManagement
należy użyć metody . Dzięki temu usługi zarządzania funkcjami, w tym filtry funkcji, są dodawane jako usługi o określonym zakresie.
services.AddScopedFeatureManagement();
integracja ASP.NET Core
Biblioteka zarządzania funkcjami udostępnia funkcje w ASP.NET Core i MVC w celu włączenia typowych scenariuszy flag funkcji w aplikacjach internetowych. Te możliwości są dostępne, odwołując się do pakietu NuGet Microsoft.FeatureManagement.AspNetCore .
Kontrolery i akcje
Kontroler MVC i akcje mogą wymagać włączenia danej funkcji lub jednej z dowolnej listy funkcji w celu wykonania. Można to zrobić przy użyciu elementu FeatureGateAttribute
, który można znaleźć w Microsoft.FeatureManagement.Mvc
przestrzeni nazw.
[FeatureGate("FeatureX")]
public class HomeController : Controller
{
…
}
Powyższe HomeController
są bramowane przez funkcję "FeatureX". Aby można było wykonać akcję zawierającą HomeController
, należy włączyć funkcję "FeatureX".
[FeatureGate("FeatureX")]
public IActionResult Index()
{
return View();
}
Powyższa Index
akcja MVC wymaga włączenia funkcji "FeatureX", zanim będzie można ją wykonać.
Wyłączona obsługa akcji
Gdy kontroler MVC lub akcja jest blokowana, ponieważ żadna z funkcji, które określa, nie jest włączona, zostanie wywołana zarejestrowana IDisabledFeaturesHandler
. Domyślnie jest rejestrowana minimalna procedura obsługi, która zwraca protokół HTTP 404. Można to przesłonić przy użyciu IFeatureManagementBuilder
flag funkcji podczas rejestrowania flag funkcji.
public interface IDisabledFeaturesHandler
{
Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}
Widok
W widokach <feature>
MVC tagi mogą służyć do warunkowego renderowania zawartości na podstawie tego, czy funkcja jest włączona, czy nie.
<feature name="FeatureX">
<p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
Możesz również negować ocenę pomocnika tagów, aby wyświetlić zawartość, gdy funkcja lub zestaw funkcji są wyłączone. negate="true"
Ustawienie w poniższym przykładzie powoduje renderowanie zawartości tylko wtedy, gdy FeatureX
jest wyłączona.
<feature negate="true" name="FeatureX">
<p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
Tag <feature>
może odwoływać się do wielu funkcji, określając rozdzielaną przecinkami listę funkcji w atrybucie name
.
<feature name="FeatureX,FeatureY">
<p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
Domyślnie wszystkie wymienione funkcje muszą być włączone, aby tag funkcji był renderowany. To zachowanie można zastąpić, dodając requirement
atrybut, jak pokazano w poniższym przykładzie.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
W widokach <feature>
MVC tagi mogą służyć do warunkowego renderowania zawartości na podstawie tego, czy funkcja jest włączona, czy też jest przypisany określony wariant funkcji. Aby uzyskać więcej informacji, zobacz sekcję wariantów .
<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>
Możesz również negować ocenę pomocnika tagów, aby wyświetlić zawartość, gdy funkcja lub zestaw funkcji są wyłączone. negate="true"
Ustawienie w poniższym przykładzie powoduje renderowanie zawartości tylko wtedy, gdy FeatureX
jest wyłączona.
<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>
Tag <feature>
może odwoływać się do wielu funkcji/wariantów, określając rozdzielaną przecinkami listę funkcji/wariantów w atrybucie/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>
Uwaga
Jeśli variant
zostanie określona, należy określić tylko jedną funkcję.
Domyślnie wszystkie wymienione funkcje muszą być włączone, aby tag funkcji był renderowany. To zachowanie można zastąpić, dodając requirement
atrybut, jak pokazano w poniższym przykładzie.
Uwaga
Jeśli element requirement
And
jest używany w połączeniu z variant
błędem, zostanie zgłoszony, ponieważ nigdy nie można przypisać wielu wariantów.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
Tag <feature>
wymaga, aby pomocnik tagu działał. Można to zrobić, dodając pomocnik tagu zarządzania funkcjami do pliku ViewImports.cshtml .
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore
Filtry MVC
Filtry akcji MVC można skonfigurować do warunkowego wykonywania na podstawie stanu funkcji. Odbywa się to przez zarejestrowanie filtrów MVC w sposób świadomy funkcji.
Potok zarządzania funkcjami obsługuje asynchroniczne filtry akcji MVC, które implementują IAsyncActionFilter
element .
services.AddMvc(o =>
{
o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});
Powyższy kod dodaje filtr MVC o nazwie SomeMvcFilter
. Ten filtr jest wyzwalany tylko w potoku MVC, jeśli opcja "FeatureX" jest włączona.
Razor Pages
Strony MVC Razor mogą wymagać włączenia danej funkcji lub jednej z dowolnej listy funkcji w celu wykonania. Można to zrobić przy użyciu elementu FeatureGateAttribute
, który można znaleźć w Microsoft.FeatureManagement.Mvc
przestrzeni nazw.
[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
Powyższy kod konfiguruje stronę Razor, aby wymagać włączenia funkcji "FeatureX". Jeśli funkcja nie jest włączona, strona generuje wynik HTTP 404 (NotFound).
W przypadku użycia na stronach Razor należy umieścić element FeatureGateAttribute
w typie procedury obsługi strony. Nie można go umieścić w poszczególnych metodach obsługi.
Kompilowanie aplikacji
Biblioteka zarządzania funkcjami może służyć do dodawania gałęzi aplikacji i oprogramowania pośredniczącego, które są wykonywane warunkowo na podstawie stanu funkcji.
app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");
Po powyższym wywołaniu aplikacja dodaje składnik oprogramowania pośredniczącego, który jest wyświetlany tylko w potoku żądania, jeśli funkcja "FeatureX" jest włączona. Jeśli funkcja jest włączona/wyłączona w czasie wykonywania, potok oprogramowania pośredniczącego można zmienić dynamicznie.
To zwiększa ogólną możliwość rozgałęziania całej aplikacji na podstawie funkcji.
app.UseForFeature(featureName, appBuilder =>
{
appBuilder.UseMiddleware<T>();
});
Implementowanie filtru funkcji
Tworzenie filtru funkcji umożliwia włączanie funkcji na podstawie zdefiniowanych kryteriów. Aby zaimplementować filtr funkcji, IFeatureFilter
należy zaimplementować interfejs. IFeatureFilter
ma jedną metodę o nazwie EvaluateAsync
. Gdy funkcja określa, że można ją włączyć dla filtru funkcji, wywoływana EvaluateAsync
jest metoda . Jeśli EvaluateAsync
funkcja zwraca true
wartość , oznacza to, że funkcja powinna być włączona.
Poniższy fragment kodu przedstawia sposób dodawania dostosowanego filtru MyCriteriaFilter
funkcji .
services.AddFeatureManagement()
.AddFeatureFilter<MyCriteriaFilter>();
Filtry funkcji są rejestrowane przez wywołanie AddFeatureFilter<T>
metody zwróconej IFeatureManagementBuilder
z AddFeatureManagement
. Te filtry funkcji mają dostęp do usług, które istnieją w kolekcji usług, która została użyta do dodawania flag funkcji. Wstrzykiwanie zależności może służyć do pobierania tych usług.
Uwaga
Gdy filtry są przywoływane w ustawieniach flagi funkcji (na przykład appsettings.json), część Filtr nazwy typu powinna zostać pominięta. Aby uzyskać więcej informacji, zobacz sekcję Filter Alias Attribute
.
Filtry funkcji sparametryzowanych
Niektóre filtry funkcji wymagają parametrów, aby zdecydować, czy funkcja powinna być włączona, czy nie. Na przykład filtr funkcji przeglądarki może włączyć funkcję dla określonego zestawu przeglądarek. Może być pożądane, aby przeglądarki Edge i Chrome włączały funkcję, a Przeglądarka Firefox nie. W tym celu można zaprojektować filtr funkcji, aby oczekiwać parametrów. Te parametry zostaną określone w konfiguracji funkcji, a w kodzie będzie dostępny za pośrednictwem FeatureFilterEvaluationContext
parametru IFeatureFilter.EvaluateAsync
.
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
ma właściwość o nazwie Parameters
. Te parametry reprezentują konfigurację nieprzetworzonej, której filtr funkcji może użyć, aby zdecydować, jak ocenić, czy funkcja powinna być włączona, czy nie. Aby ponownie użyć filtru funkcji przeglądarki jako przykładu, filtr może użyć Parameters
do wyodrębnienia zestawu dozwolonych przeglądarek, które zostaną określone dla tej funkcji, a następnie sprawdź, czy żądanie jest wysyłane z jednej z tych przeglądarek.
[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
}
}
Filtruj atrybut aliasu
Po zarejestrowaniu filtru funkcji dla flagi funkcji alias używany w konfiguracji jest nazwą typu filtru funkcji z sufiksem Filtr , jeśli istnieje, usunięty. Na przykład MyCriteriaFilter
zostanie określona jako MyCriteria w konfiguracji.
"MyFeature": {
"EnabledFor": [
{
"Name": "MyCriteria"
}
]
}
Można to przesłonić przy użyciu elementu FilterAliasAttribute
. Filtr funkcji można dekorować za pomocą tego atrybutu, aby zadeklarować nazwę, która powinna być używana w konfiguracji do odwołowania się do tego filtru funkcji w ramach flagi funkcji.
Brakujące filtry funkcji
Jeśli funkcja jest skonfigurowana do włączenia dla określonego filtru funkcji i ten filtr funkcji nie jest zarejestrowany, podczas oceny funkcji jest zgłaszany wyjątek. Wyjątek można wyłączyć przy użyciu opcji zarządzania funkcjami.
services.Configure<FeatureManagementOptions>(options =>
{
options.IgnoreMissingFeatureFilters = true;
});
Korzystanie z obiektu HttpContext
Filtry funkcji mogą ocenić, czy funkcja powinna być włączona na podstawie właściwości żądania HTTP. Jest to wykonywane przez sprawdzenie kontekstu HTTP. Filtr funkcji może uzyskać odwołanie do kontekstu HTTP, uzyskując IHttpContextAccessor
wstrzyknięcie zależności.
public class BrowserFilter : IFeatureFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public BrowserFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
}
Należy dodać element IHttpContextAccessor
do kontenera wstrzykiwania zależności podczas uruchamiania, aby był dostępny. Można go zarejestrować w metodzie IServiceCollection
przy użyciu następującej metody.
public void ConfigureServices(IServiceCollection services)
{
…
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
…
}
Zaawansowane: IHttpContextAccessor
/HttpContext
nie należy używać w składnikach Razor aplikacji Blazor po stronie serwera. Zalecaną metodą przekazywania kontekstu http w aplikacjach Platformy Blazor jest skopiowanie danych do usługi o określonym zakresie. W przypadku aplikacji AddScopedFeatureManagement
Platformy Blazor należy używać do rejestrowania usług zarządzania funkcjami. Aby uzyskać więcej informacji, zobacz sekcję Scoped Feature Management Services
.
Podawanie kontekstu oceny funkcji
W aplikacjach konsolowych nie ma kontekstu otoczenia, takiego jak HttpContext
filtry funkcji, które mogą uzyskać i wykorzystać, aby sprawdzić, czy funkcja powinna być włączona lub wyłączona. W takim przypadku aplikacje muszą podać obiekt reprezentujący kontekst w systemie zarządzania funkcjami do użycia przez filtry funkcji. Odbywa się to przy użyciu polecenia IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext)
. Obiekt appContext udostępniany menedżerowi funkcji może służyć przez filtry funkcji do oceny stanu funkcji.
MyAppContext context = new MyAppContext
{
AccountId = current.Id;
}
if (await featureManager.IsEnabledAsync(feature, context))
{
…
}
Filtry funkcji kontekstowych
Filtry funkcji kontekstowych implementują IContextualFeatureFilter<TContext>
interfejs. Te specjalne filtry funkcji mogą korzystać z kontekstu przekazywanego, gdy IFeatureManager.IsEnabledAsync<TContext>
jest wywoływany. Parametr TContext
typu w temacie IContextualFeatureFilter<TContext>
opisuje typ kontekstu, który filtr może obsługiwać. Dzięki temu deweloper filtru funkcji kontekstowych może opisać, co jest wymagane dla tych, którzy chcą z niego korzystać. Ponieważ każdy typ jest elementem potomnym obiektu, filtr, który implementuje, może być wywoływany IContextualFeatureFilter<object>
dla dowolnego dostarczonego kontekstu. Aby zilustrować przykład bardziej szczegółowego filtru funkcji kontekstowych, należy rozważyć funkcję włączoną, jeśli konto znajduje się na skonfigurowanej liście włączonych kont.
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
}
}
Widzimy, że AccountIdFilter
wymagany jest obiekt, który implementuje IAccountContext
, aby móc ocenić stan funkcji. W przypadku korzystania z tego filtru funkcji obiekt wywołujący musi upewnić się, że przekazany obiekt implementuje IAccountContext
element .
Uwaga
Tylko jeden interfejs filtru funkcji może być implementowany przez jeden typ. Próba dodania filtru funkcji, który implementuje więcej niż jeden interfejs filtru funkcji, powoduje wyświetlenie elementu ArgumentException
.
Używanie kontekstowych i nie kontekstowych filtrów z tym samym aliasem
Filtry elementów IFeatureFilter
i IContextualFeatureFilter
mogą współużytkować ten sam alias. W szczególności można mieć jeden alias filtru współużytkowany przez 0 lub 1 IFeatureFilter
i 0 lub N IContextualFeatureFilter<ContextType>
, o ile istnieje co najwyżej jeden odpowiedni filtr dla ContextType
.
W poniższym fragmencie opisano proces wybierania filtru, gdy kontekstowe i nie kontekstowe filtry o tej samej nazwie są rejestrowane w aplikacji.
Załóżmy, że masz filtr nie kontekstowy o nazwie FilterA
i dwa filtry FilterB
kontekstowe i FiltrC, które akceptują TypeB
i TypeC
konteksty odpowiednio. Wszystkie trzy filtry mają ten sam alias SharedFilterName
.
Masz również flagę MyFeature
funkcji, która używa filtru SharedFilterName
funkcji w jego konfiguracji.
Jeśli wszystkie trzy filtry są zarejestrowane:
- Podczas wywoływania metody IsEnabledAsync("MyFeature"),
FilterA
element jest używany do oceny flagi funkcji. - Podczas wywoływania metody IsEnabledAsync("MyFeature", kontekstu), jeśli typ kontekstu to
TypeB
,FilterB
jest używany. Jeśli typ kontekstu toTypeC
,FilterC
jest używany. - Podczas wywoływania metody IsEnabledAsync("MyFeature", kontekstu), jeśli typ kontekstu to
TypeF
,FilterA
jest używany.
Wbudowane filtry funkcji
Istnieje kilka filtrów funkcji, które są dostarczane z pakietemMicrosoft.FeatureManagement
: PercentageFilter
, TimeWindowFilter
ContextualTargetingFilter
i TargetingFilter
. Wszystkie filtry, z wyjątkiem TargetingFilter
, są dodawane automatycznie , gdy zarządzanie funkcjami jest rejestrowane za pomocą AddFeatureManagement
metody. Element TargetingFilter
jest dodawany przy użyciu WithTargeting
metody, która jest szczegółowa w poniższej Targeting
sekcji.
Każdy z wbudowanych filtrów funkcji ma własne parametry. Oto lista filtrów funkcji wraz z przykładami.
Microsoft.Percentage
Ten filtr zapewnia możliwość włączenia funkcji na podstawie ustawionej wartości procentowej.
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.Percentage",
"Parameters": {
"Value": 50
}
}
]
}
Microsoft.TimeWindow
Ten filtr zapewnia możliwość włączenia funkcji na podstawie przedziału czasu. End
Jeśli tylko zostanie określona, funkcja jest rozważana do tego czasu. Start
Jeśli tylko zostanie określona, funkcja jest uwzględniana we wszystkich punktach po tym czasie.
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.TimeWindow",
"Parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
}
Przedział czasu można skonfigurować do okresowego powtarzania. Może to być przydatne w scenariuszach, w których może być konieczne włączenie funkcji w okresie niskiego lub dużego ruchu w ciągu dnia lub w określonych dniach tygodnia. Aby rozwinąć poszczególne przedziały czasu do okresów cyklicznych, reguła cyklu powinna być określona w parametrze Recurrence
.
Uwaga
Start
i End
muszą być określone, aby włączyć Recurrence
.
"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"
}
}
}
}
]
}
Ustawienia Recurrence
składają się z dwóch części: Pattern
(jak często powtarza się przedział czasu) i Range
(jak długo powtarza się wzorzec cyklu).
Wzorzec cyklu
Istnieją dwa możliwe typy wzorców cyklu: Daily
i Weekly
. Na przykład przedział czasu może powtarzać "codziennie", "co trzy dni", "każdy poniedziałek" lub "co drugi piątek".
W zależności od typu niektóre pola Pattern
są wymagane, opcjonalne lub ignorowane.
Daily
Wzorzec cyklu dziennego powoduje powtarzanie przedziału czasu na podstawie liczby dni między poszczególnymi wystąpieniami.
Właściwości Stopień zgodności opis Type Wymagania Musi być ustawiona wartość Daily
.Interwał Opcjonalnie Określa liczbę dni między poszczególnymi wystąpieniami. Wartość domyślna to 1. Weekly
Wzorzec cyklu tygodniowego powoduje powtórzenie przedziału czasu w tym samym dniu lub dniach tygodnia na podstawie liczby tygodni między poszczególnymi zestawami wystąpień.
Właściwości Stopień zgodności opis Type Wymagania Musi być ustawiona wartość Weekly
.DaysOfWeek Wymagania Określa dni tygodnia, w których występuje zdarzenie. Interwał Opcjonalnie Określa liczbę tygodni między poszczególnymi zestawami wystąpień. Wartość domyślna to 1. FirstDayOfWeek Opcjonalnie Określa, który dzień jest uważany za pierwszy dzień tygodnia. Wartość domyślna to Sunday
.Poniższy przykład powtarza przedział czasu co drugi poniedziałek i wtorek
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Uwaga
Start
musi być prawidłowym pierwszym wystąpieniem, które pasuje do wzorca cyklu. Ponadto czas trwania przedziału czasu nie może być dłuższy niż częstotliwość jego wystąpienia. Na przykład jest nieprawidłowe, aby codziennie powtarzać 25-godzinne okno czasu.
Zakres cyklu
Istnieją trzy możliwe typy zakresów cykli: NoEnd
, EndDate
i Numbered
.
NoEnd
Zakres
NoEnd
powoduje, że cykl występuje w nieskończoność.Właściwości Stopień zgodności opis Type Wymagania Musi być ustawiona wartość NoEnd
.EndDate
Zakres
EndDate
powoduje, że przedział czasu występuje we wszystkich dniach, które pasują do odpowiedniego wzorca do daty zakończenia.Właściwości Stopień zgodności opis Type Wymagania Musi być ustawiona wartość EndDate
.EndDate Wymagania Określa datę zakończenia stosowania wzorca. O ile godzina rozpoczęcia ostatniego wystąpienia spadnie przed datą zakończenia, czas zakończenia tego wystąpienia może wykraczać poza nią. Poniższy przykład będzie powtarzał przedział czasu każdego dnia do czasu ostatniego wystąpienia 1 kwietnia 2024 r.
"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
Zakres
Numbered
powoduje, że przedział czasu występuje stałą liczbę razy (na podstawie wzorca).Właściwości Stopień zgodności opis Type Wymagania Musi być ustawiona wartość Numbered
.NumberOfOccurrences Wymagania Określa liczbę wystąpień. Poniższy przykład powtórzy przedział czasu w poniedziałek i wtorek do trzech wystąpień, które mają miejsce odpowiednio 1 kwietnia (Mon), 2 kwietnia (wt) i 8 kwietnia (Mon).
"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 } }
Aby utworzyć regułę cyklu, należy określić wartości i Pattern
Range
. Dowolny typ wzorca może pracować z dowolnym typem zakresu.
Zaawansowane: przesunięcie strefy czasowej Start
właściwości jest stosowane do ustawień cyklu.
Microsoft.Targeting
Ten filtr zapewnia możliwość włączenia funkcji dla odbiorców docelowych. Szczegółowe wyjaśnienie określania wartości docelowej zostało wyjaśnione w poniższej sekcji określania wartości docelowej . Parametry filtru obejmują obiekt opisujący Audience
użytkowników, grupy, wykluczonych użytkowników/grup oraz domyślny procent bazy użytkowników, który powinien mieć dostęp do funkcji. Każdy obiekt grupy wymieniony w Groups
sekcji musi również określić, jaki procent członków grupy powinien mieć dostęp. Jeśli użytkownik jest określony w Exclusion
sekcji , bezpośrednio lub jeśli użytkownik znajduje się w wykluczonej grupie, funkcja jest wyłączona. W przeciwnym razie, jeśli użytkownik jest określony bezpośrednio w Users
sekcji lub jeśli użytkownik znajduje się w uwzględnionych procentach dowolnego wdrożenia grupy, lub jeśli użytkownik mieści się w domyślnym procentu wdrożenia, ten użytkownik będzie miał włączoną funkcję.
"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"
]
}
}
}
}
]
}
Przestrzenie nazw aliasu filtru funkcji
Wszystkie wbudowane aliasy filtru funkcji znajdują się w Microsoft
przestrzeni nazw filtru funkcji. Zapobiega to konfliktom z innymi filtrami funkcji, które mogą współużytkować ten sam alias. Segmenty przestrzeni nazw filtru funkcji są dzielone przez znak "". Filtr funkcji można odwoływać się do jego w pełni kwalifikowanego aliasu, takiego jak Microsoft.Percentage
lub ostatniego segmentu Microsoft.Percentage
, który w przypadku elementu to Percentage
.
Określanie celu
Określanie wartości docelowej to strategia zarządzania funkcjami, która umożliwia deweloperom stopniowe wdrażanie nowych funkcji w bazie użytkowników. Strategia jest oparta na koncepcji określania celu grupy użytkowników znanej jako docelowa grupa odbiorców. Grupa odbiorców składa się z określonych użytkowników, grup, wykluczonych użytkowników/grup oraz wyznaczonego procentu całej bazy użytkowników. Grupy, które są uwzględnione w grupie odbiorców, można podzielić dalej na wartości procentowe ich całkowitej liczby członków.
W poniższych krokach przedstawiono przykład progresywnego wdrożenia nowej funkcji "Beta":
- Indywidualni użytkownicy Jeff i Alicia otrzymują dostęp do wersji beta
- Inny użytkownik, Mark, prosi o wyrażenie zgody i jest uwzględniony.
- Dwadzieścia procent grupy znanej jako "Ring1" użytkowników jest uwzględnionych w wersji beta.
- Liczba użytkowników "Ring1" uwzględnionych w wersji beta wzrosła do 100 procent.
- Pięć procent bazy użytkowników jest uwzględnionych w wersji beta.
- Procent wdrożenia jest wyprzedzony do 100 procent, a funkcja jest całkowicie wdrażana.
Ta strategia wdrażania funkcji jest wbudowana w bibliotekę za pomocą dołączonego filtru funkcji Microsoft.Targeting .
Określanie wartości docelowej w aplikacji internetowej
Przykładowa aplikacja internetowa korzystająca z filtru funkcji określania wartości docelowej jest dostępna w przykładowym projekcie FeatureFlagDemo .
Aby rozpocząć korzystanie z TargetingFilter
elementu w aplikacji, należy dodać go do kolekcji usług aplikacji tak samo jak każdy inny filtr funkcji. W przeciwieństwie do innych wbudowanych filtrów funkcja TargetingFilter
opiera się na innej usłudze, która ma zostać dodana do kolekcji usług aplikacji. Ta usługa jest usługą ITargetingContextAccessor
.
Microsoft.FeatureManagement.AspNetCore
Udostępnia domyślną implementację ITargetingContextAccessor
, z której będą wyodrębniać informacje dotyczące określania HttpContext
wartości docelowej z żądania . Domyślne metody określania kontekstu określania wartości docelowej można użyć podczas konfigurowania określania wartości docelowej przy użyciu przeciążenia niegenerycznego WithTargeting
w obiekcie IFeatureManagementBuilder
.
Domyślna metoda dostępu kontekstu określania wartości docelowej i TargetingFilter
jest rejestrowana przez wywołanie WithTargeting
metody IFeatureManagementBuilder
.
services.AddFeatureManagement()
.WithTargeting();
Możesz również zarejestrować niestandardową implementację dla ITargetingContextAccessor
elementu i TargetingFilter
przez wywołanie metody WithTargeting<T>
. Oto przykład konfigurowania zarządzania funkcjami w aplikacji internetowej do użycia z TargetingFilter
implementacją ITargetingContextAccessor
o nazwie ExampleTargetingContextAccessor
.
services.AddFeatureManagement()
.WithTargeting<ExampleTargetingContextAccessor>();
ITargetingContextAccessor
Aby można było używać TargetingFilter
elementu w aplikacji internetowej, wymagana jest implementacja ITargetingContextAccessor
. Dzieje się tak dlatego, że w przypadku przeprowadzenia oceny docelowej potrzebne są informacje kontekstowe, takie jak aktualnie oceniany użytkownik. Te informacje są nazywane .TargetingContext
Różne aplikacje mogą wyodrębniać te informacje z różnych miejsc. Niektóre typowe przykłady, w których aplikacja może ściągać kontekst określania wartości docelowej, to kontekst HTTP żądania lub baza danych.
Przykład wyodrębniania informacji kontekstowych z kontekstu HTTP aplikacji jest DefaultHttpTargetingContextAccessor
dostarczany przez Microsoft.FeatureManagement.AspNetCore
pakiet. Spowoduje to wyodrębnienie informacji o określaniu wartości docelowej z elementu HttpContext.User
. UserId
informacje zostaną wyodrębnione z Identity.Name
pola, a Groups
informacje zostaną wyodrębnione z oświadczeń typu Role
. Ta implementacja opiera się na użyciu IHttpContextAccessor
elementu , który został omówiony tutaj.
Określanie wartości docelowej w aplikacji konsolowej
Filtr określania wartości docelowej opiera się na kontekście określania wartości docelowej, aby ocenić, czy funkcja powinna być włączona. Ten kontekst określania wartości docelowej zawiera informacje, takie jak aktualnie oceniany użytkownik i grupy użytkowników. W aplikacjach konsoli zwykle nie ma dostępnego kontekstu otoczenia, aby przekazać te informacje do filtru określania wartości docelowej, dlatego należy przekazać je bezpośrednio po FeatureManager.IsEnabledAsync
wywołaniu. Jest to obsługiwane przy użyciu elementu ContextualTargetingFilter
. Aplikacje, które muszą umieścić kontekst docelowy w menedżerze funkcji, powinny używać tego elementu zamiast TargetingFilter.
Ponieważ ContextualTargetingFilter
element jest elementem IContextualTargetingFilter<ITargetingContext>
, należy przekazać do niej implementację ITargetingContext
, aby IFeatureManager.IsEnabledAsync
można było ocenić i włączyć funkcję.
IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
UserId = userId,
Groups = groups
};
await fm.IsEnabledAsync(featureName, targetingContext);
Nadal ContextualTargetingFilter
używa aliasu filtru funkcji Microsoft.Targeting, więc konfiguracja tego filtru jest zgodna z tym, co zostało wymienione w tej sekcji.
Przykład użycia ContextualTargetingFilter
elementu w aplikacji konsolowej jest dostępny w przykładowym projekcie TargetConsoleApp .
Opcje oceny określania wartości docelowej
Dostępne są opcje dostosowywania sposobu oceny określania wartości docelowej we wszystkich funkcjach. Te opcje można skonfigurować podczas konfigurowania zarządzania funkcjami.
services.Configure<TargetingEvaluationOptions>(options =>
{
options.IgnoreCase = true;
});
Wykluczanie określania wartości docelowej
Podczas definiowania grupy odbiorców można wykluczyć użytkowników i grupy z odbiorców. Jest to przydatne, gdy funkcja jest wdrażana w grupie użytkowników, ale kilka użytkowników lub grup musi zostać wykluczonych z wdrożenia. Wykluczenie jest definiowane przez dodanie listy użytkowników i grup do Exclusion
właściwości odbiorców.
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
W powyższym przykładzie funkcja jest włączona dla użytkowników o nazwach Jeff
i Alicia
. Jest ona również włączona dla użytkowników w grupie o nazwie Ring0
. Jeśli jednak użytkownik ma nazwę Mark
, funkcja jest wyłączona, niezależnie od tego, czy znajdują się w grupie Ring0
, czy nie. Wykluczenia mają priorytet nad resztą filtru określania wartości docelowej.
Warianty
Po dodaniu nowych funkcji do aplikacji może dojść do czasu, gdy funkcja ma wiele różnych proponowanych opcji projektowania. Typowym rozwiązaniem do podejmowania decyzji o projekcie jest pewna forma testowania A/B, która polega na udostępnieniu innej wersji funkcji różnym segmentom bazy użytkowników i wybraniu wersji na podstawie interakcji użytkownika. W tej bibliotece ta funkcja jest włączona przez reprezentowanie różnych konfiguracji funkcji z wariantami.
Warianty umożliwiają flagę funkcji stać się bardziej niż prostą flagą włączania/wyłączania. Wariant reprezentuje wartość flagi funkcji, która może być ciągiem, liczbą, wartością logiczną, a nawet obiektem konfiguracji. Flaga funkcji, która deklaruje warianty, powinna określać, w jakich okolicznościach należy używać każdego wariantu, co zostało szczegółowo omówione w sekcji Przydzielanie wariantów .
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; }
}
Pobieranie wariantów
Dla każdej funkcji można pobrać wariant przy użyciu IVariantFeatureManager
metody "s 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
Po pobraniu wariantu można użyć konfiguracji wariantu bezpośrednio jako IConfigurationSection
właściwości wariantu Configuration
. Inną opcją jest powiązanie konfiguracji z obiektem przy użyciu polecenia . Wzorzec powiązania konfiguracji platformy NET.
IConfigurationSection variantConfiguration = variant.Configuration;
MyFeatureSettings settings = new MyFeatureSettings();
variantConfiguration.Bind(settings);
Zwrócony wariant jest zależny od aktualnie ocenianego użytkownika, a informacje te są uzyskiwane z wystąpienia klasy TargetingContext
. Ten kontekst można przekazać podczas wywoływania GetVariantAsync
lub można go automatycznie pobrać z implementacji ITargetingContextAccessor
, jeśli jest zarejestrowany.
Deklaracja flagi funkcji wariantu
W porównaniu z flagami funkcji normalnych flagi funkcji wariantu mają dwie dodatkowe właściwości: variants
i allocation
. Właściwość variants
jest tablicą zawierającą warianty zdefiniowane dla tej funkcji. Właściwość allocation
definiuje sposób przydzielania tych wariantów dla funkcji. Podobnie jak deklarowanie flag funkcji normalnych, można skonfigurować flagi funkcji wariantu w pliku json. Oto przykład flagi funkcji wariantu.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
Definiowanie wariantów
Każdy wariant ma dwie właściwości: nazwę i konfigurację. Nazwa jest używana do odwoływania się do określonego wariantu, a konfiguracja jest wartością tego wariantu. Konfigurację można ustawić przy użyciu configuration_value
właściwości . configuration_value
jest konfiguracją śródliniową, która może być ciągiem, liczbą, wartością logiczną lub obiektem konfiguracji. Jeśli configuration_value
nie zostanie określony, zwrócona właściwość wariantu Configuration
będzie mieć wartość null.
Lista wszystkich możliwych wariantów jest zdefiniowana dla każdej funkcji w variants
ramach właściwości .
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
Przydzielanie wariantów
Proces przydzielania wariantów funkcji zależy od allocation
właściwości funkcji.
"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"
}
]
Ustawienie allocation
funkcji ma następujące właściwości:
Właściwości | opis |
---|---|
default_when_disabled |
Określa, który wariant ma być używany, gdy jest wymagany wariant, gdy funkcja jest uznawana za wyłączoną. |
default_when_enabled |
Określa, który wariant ma być używany, gdy jest wymagany wariant, gdy funkcja jest uznawana za włączoną i żaden inny wariant nie został przypisany do użytkownika. |
user |
Określa wariant i listę użytkowników, do których należy przypisać ten wariant. |
group |
Określa wariant i listę grup. Wariant zostanie przypisany, jeśli użytkownik znajduje się w co najmniej jednej grupie. |
percentile |
Określa wariant i zakres procentowy, do którego ma zostać przypisana wartość procentowa obliczona przez użytkownika. |
seed |
Wartość, na podstawie której są obliczane percentile wartości procentowe. Obliczanie procentowe dla określonego użytkownika będzie takie samo we wszystkich funkcjach, jeśli jest używana ta sama seed wartość. Jeśli nie seed zostanie określony, zostanie utworzony domyślny inicjator na podstawie nazwy funkcji. |
W powyższym przykładzie, jeśli funkcja nie jest włączona, menedżer funkcji przypisze wariant oznaczony jako default_when_disabled
do bieżącego użytkownika, który jest Small
w tym przypadku.
Jeśli funkcja jest włączona, menedżer funkcji sprawdzi user
w tym celu alokacje , group
i percentile
w celu przypisania wariantu. W tym konkretnym przykładzie, jeśli oceniany użytkownik ma nazwę Marsha
, w grupie o nazwie Ring1
lub użytkownik może spaść między 0 a 10. percentylem, określony wariant zostanie przypisany do użytkownika. W takim przypadku wszystkie te elementy zwróciłyby Big
wariant. Jeśli żadna z tych alokacji nie jest zgodna default_when_enabled
, użytkownik ma przypisany wariant , czyli Small
.
Logika alokacji jest podobna do filtru funkcji Microsoft.Targeting, ale istnieją pewne parametry, które znajdują się w określaniu wartości docelowej, które nie znajdują się w alokacji i na odwrót. Wyniki określania wartości docelowej i alokacji nie są powiązane.
Uwaga
Aby zezwolić na przydzielanie wariantów funkcji, należy zarejestrować element ITargetingContextAccessor
. Można to zrobić, wywołując metodę WithTargeting<T>
.
Zastępowanie stanu włączonego z wariantem
Można użyć wariantów, aby zastąpić włączony stan flagi funkcji. Daje to wariantom możliwość rozszerzenia oceny flagi funkcji. Podczas wywoływania IsEnabled
flagi z wariantami menedżer funkcji sprawdzi, czy wariant przypisany do bieżącego użytkownika jest skonfigurowany do zastąpienia wyniku. Odbywa się to przy użyciu opcjonalnej właściwości status_override
wariantu . Domyślnie ta właściwość jest ustawiona na None
, co oznacza, że wariant nie ma wpływu na to, czy flaga jest uznawana za włączoną, czy wyłączoną. Ustawienie status_override
zezwala na Enabled
włączenie wariantu, po wybraniu, przesłonięcia flagi. Ustawienie status_override
na Disabled
wartość zapewnia przeciwną funkcjonalność, dlatego wyłączenie flagi po wybraniu wariantu. Nie można zastąpić funkcji ze stanem enabled
false
.
Jeśli używasz flagi funkcji z wariantami binarnymi, status_override
właściwość może być bardzo pomocna. Umożliwia to kontynuowanie korzystania z interfejsów API, takich jak IsEnabledAsync
i FeatureGateAttribute
w aplikacji, a jednocześnie korzystanie z nowych funkcji, które są dostępne z wariantami, takimi jak alokacja percentylu i inicjowanie.
{
"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"
}
]
}
W powyższym przykładzie funkcja jest zawsze włączona. Jeśli bieżący użytkownik znajduje się w obliczonym zakresie percentylu od 10 do 20, On
zwracany jest wariant. Off
W przeciwnym razie zwracany jest wariant i ponieważ status_override
jest równy Disabled
, funkcja zostanie teraz uznana za wyłączoną.
Warianty iniekcji zależności
Flagi funkcji wariantu mogą być używane w połączeniu z iniekcją zależności, aby wyświetlić różne implementacje usługi dla różnych użytkowników. Jest to realizowane przy użyciu interfejsu IVariantServiceProvider<TService>
.
IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...
IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken);
W powyższym IVariantServiceProvider<IAlgorithm>
fragmencie kodu pobiera implementację IAlgorithm
z kontenera wstrzykiwania zależności. Wybrana implementacja jest zależna od:
- Flaga funkcji zarejestrowana w
IAlgorithm
usłudze. - Przydzielony wariant dla tej funkcji.
Element IVariantServiceProvider<T>
jest udostępniany aplikacji przez wywołanie metody IFeatureManagementBuilder.WithVariantService<T>(string featureName)
. Zobacz przykład poniżej.
services.AddFeatureManagement()
.WithVariantService<IAlgorithm>("ForecastAlgorithm");
Powyższe wywołanie udostępnia IVariantServiceProvider<IAlgorithm>
w kolekcji usług. Implementacje IAlgorithm
programu muszą być dodawane oddzielnie za pomocą metody add, takiej jak services.AddSingleton<IAlgorithm, SomeImplementation>()
. Implementacja IAlgorithm
tej IVariantServiceProvider
funkcji zależy od flagi funkcji wariantu ForecastAlgorithm
. Jeśli do kolekcji usług nie zostanie dodana żadna IAlgorithm
implementacja, IVariantServiceProvider<IAlgorithm>.GetServiceAsync()
funkcja zwraca zadanie z wynikiem null .
{
// The example variant feature flag
"id": "ForecastAlgorithm",
"enabled": true,
"variants": [
{
"Name": "AlgorithmBeta"
},
...
]
}
Atrybut aliasu usługi wariantu
[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
...
}
Dostawca usług wariantu będzie używać nazw typów implementacji do dopasowania przydzielonego wariantu. Jeśli usługa wariantu jest ozdobiona wartością , nazwa zadeklarowana w tym atrybucie VariantServiceAliasAttribute
powinna być używana w konfiguracji do odwołowania się do tej usługi wariantu.
Telemetria
Po wdrożeniu zmiany flagi funkcji często ważne jest analizowanie jej wpływu na aplikację. Oto na przykład kilka pytań, które mogą wystąpić:
- Czy moje flagi są włączone/wyłączone zgodnie z oczekiwaniami?
- Czy docelowi użytkownicy uzyskują dostęp do określonej funkcji zgodnie z oczekiwaniami?
- Który wariant jest widoczny dla określonego użytkownika?
Odpowiedzi na te typy pytań można uzyskać za pośrednictwem emisji i analizy zdarzeń oceny flag funkcji. Ta biblioteka używa interfejsu System.Diagnostics.Activity
API do tworzenia danych telemetrycznych śledzenia podczas oceny flagi funkcji.
Włączanie telemetrii
Domyślnie flagi funkcji nie mają emitowanych danych telemetrycznych. Aby opublikować dane telemetryczne dla danej flagi funkcji, flaga MUSI zadeklarować , że jest włączona dla emisji telemetrii.
W przypadku flag funkcji zdefiniowanych w appsettings.json
programie jest to wykonywane przy użyciu telemetry
właściwości .
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
Powyższy fragment kodu appsettings definiuje flagę funkcji o nazwie MyFeatureFlag
, która jest włączona dla telemetrii. Jest to wskazywane przez telemetry
obiekt, który ustawia wartość enabled
true. Wartość enabled
właściwości musi być true
publikowania danych telemetrycznych dla flagi.
Sekcja telemetry
flagi funkcji ma następujące właściwości:
Właściwości | opis |
---|---|
enabled |
Określa, czy dane telemetryczne mają być publikowane dla flagi funkcji. |
metadata |
Kolekcja par klucz-wartość, modelowana jako słownik, która może służyć do dołączania niestandardowych metadanych dotyczących flagi funkcji do zdarzeń oceny. |
Publikowanie niestandardowych danych telemetrycznych
Menedżer funkcji ma własną ActivitySource
nazwę "Microsoft.FeatureManagement". Jeśli telemetry
flaga funkcji jest włączona, za każdym razem, gdy zostanie uruchomiona ocena flagi funkcji, menedżer funkcji uruchomi element Activity
. Po zakończeniu oceny flagi funkcji menedżer funkcji doda ActivityEvent
nazwę FeatureFlag
do bieżącego działania. Zdarzenie FeatureFlag
będzie zawierać tagi, które zawierają informacje o ocenie flagi funkcji, zgodnie z polami zdefiniowanymi w schemacie FeatureEvaluationEvent .
Uwaga
Wszystkie pary wartości klucza określone w telemetry.metadata
flagi funkcji zostaną również uwzględnione w tagach.
Aby włączyć publikowanie niestandardowych danych telemetrycznych, możesz utworzyć ActivityListener
źródło działań i nasłuchiwać go Microsoft.FeatureManagement
. Oto przykład pokazujący, jak nasłuchiwać źródła działań zarządzania funkcjami i dodawać wywołanie zwrotne po ocenie funkcji.
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.
}
}
});
Aby uzyskać więcej informacji, zobacz Zbieranie rozproszonego śledzenia.
Wydawca telemetrii usługi Application Insights
Pakiet Microsoft.FeatureManagement.Telemetry.ApplicationInsights
udostępnia wbudowanego wydawcę telemetrii, który wysyła dane oceny flag funkcji do usługi Application Insights. Aby skorzystać z tego celu, dodaj odwołanie do pakietu i zarejestruj wydawcę telemetrii usługi Application Insights, jak pokazano poniżej.
builder.services
.AddFeatureManagement()
.AddApplicationInsightsTelemetryPublisher();
Pakiet Microsoft.FeatureManagement.Telemetry.ApplicationInsights
udostępnia inicjator telemetrii, który automatycznie taguje wszystkie zdarzenia za pomocą TargetingId
polecenia , aby zdarzenia mogły być połączone z ocenami flag. Aby użyć inicjatora telemetrii, TargetingTelemetryInitializer
dodaj go do kolekcji usług aplikacji.
builder.Services.AddSingleton<ITelemetryInitializer, TargetingTelemetryInitializer>();
Uwaga
Aby upewnić się, że TargetingTelemetryInitializer
działa zgodnie z oczekiwaniami, należy użyć opisanego TargetingHttpContextMiddleware
poniżej.
Aby włączyć trwałość kontekstu określania wartości docelowej w bieżącym działaniu, możesz użyć elementu TargetingHttpContextMiddleware
.
app.UseMiddleware<TargetingHttpContextMiddleware>();
Przykład użycia można znaleźć w przykładzie VariantAndTelemetryDemo .
Warunek wstępny
Ten wydawca telemetrii zależy od tego, czy usługa Application Insights jest już skonfigurowana jako usługa aplikacji. Można to zrobić na przykład w przykładowej aplikacji.
Ten wydawca danych telemetrycznych zależy od tego, czy usługa Application Insights jest już skonfigurowana i zarejestrowana jako usługa aplikacji.
Buforowanie
Stan funkcji jest dostarczany przez IConfiguration
system. Wszelkie buforowanie i dynamiczne aktualizowanie powinny być obsługiwane przez dostawców konfiguracji. Menedżer funkcji prosi o IConfiguration
najnowszą wartość stanu funkcji za każdym razem, gdy zostanie sprawdzona opcja włączenia funkcji.
Snapshot
Istnieją scenariusze, które wymagają, aby stan funkcji pozostał spójny w okresie istnienia żądania. Wartości zwrócone ze standardu IFeatureManager
mogą ulec zmianie, jeśli IConfiguration
źródło, z którego jest pobierane, zostanie zaktualizowane podczas żądania. Można temu zapobiec za pomocą polecenia IFeatureManagerSnapshot
. IFeatureManagerSnapshot
można pobrać w taki sam sposób, jak IFeatureManager
. IFeatureManagerSnapshot
implementuje interfejs IFeatureManager
elementu , ale buforuje pierwszy oceniany stan funkcji podczas żądania i zwraca ten sam stan funkcji w okresie jego istnienia.
Dostawcy funkcji niestandardowych
Implementowanie niestandardowego dostawcy funkcji umożliwia deweloperom ściąganie flag funkcji ze źródeł, takich jak baza danych lub usługa zarządzania funkcjami. Dołączony dostawca funkcji, który jest używany domyślnie ściąga flagi funkcji z systemu konfiguracji platformy .NET Core. Umożliwia to zdefiniowanie funkcji w pliku appsettings.json lub u dostawców konfiguracji, takich jak aplikacja systemu Azure Configuration. To zachowanie można zastąpić, aby zapewnić pełną kontrolę nad tym, skąd są odczytywane definicje funkcji.
Aby dostosować ładowanie definicji funkcji, należy zaimplementować IFeatureDefinitionProvider
interfejs.
public interface IFeatureDefinitionProvider
{
Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);
IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}
Aby można było użyć implementacji IFeatureDefinitionProvider
programu , należy ją dodać do kolekcji usług przed dodaniem zarządzania funkcjami. Poniższy przykład dodaje implementację IFeatureDefinitionProvider
o nazwie InMemoryFeatureDefinitionProvider
.
services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
.AddFeatureManagement()
Następne kroki
Aby dowiedzieć się, jak używać flag funkcji w aplikacjach, przejdź do następujących przewodników Szybki start.
Aby dowiedzieć się, jak używać filtrów funkcji, przejdź do następujących samouczków.