Gerenciamento de recursos .NET
A biblioteca de gerenciamento de recursos .NET fornece uma maneira de desenvolver e expor a funcionalidade do aplicativo com base em sinalizadores de recursos. Uma vez que um novo recurso é desenvolvido, muitos aplicativos têm requisitos especiais, como quando o recurso deve ser ativado e em que condições. Essa biblioteca fornece uma maneira de definir essas relações e também se integra a padrões de código .NET comuns para tornar possível a exposição desses recursos.
Os sinalizadores de recursos fornecem uma maneira para os aplicativos .NET e ASP.NET Core ativarem ou desativarem recursos dinamicamente. Os desenvolvedores podem usar sinalizadores de recursos em casos de uso simples, como instruções condicionais para cenários mais avançados, como adicionar rotas condicionalmente ou filtros MVC. Os sinalizadores de recursos são criados sobre o sistema de configuração do .NET Core. Qualquer provedor de configuração do .NET Core é capaz de atuar como a espinha dorsal para sinalizadores de recursos.
Aqui estão alguns dos benefícios de usar a biblioteca de gerenciamento de recursos .NET:
Uma convenção comum para o gerenciamento de recursos
Baixa barreira à entrada
- Construído sobre
IConfiguration
- Suporta a configuração do sinalizador de recurso de arquivo JSON
- Construído sobre
Gerenciamento do tempo de vida do sinalizador de recursos
- Os valores de configuração podem mudar em tempo real; Os sinalizadores de recursos podem ser consistentes em toda a solicitação
Cenários simples a complexos cobertos
- Ativar e desativar recursos por meio do arquivo de configuração declarativa
- Avalie dinamicamente o estado do recurso com base na chamada para o servidor
Extensões de API para ASP.NET Core e MVC framework
- Encaminhamento
- Filtros
- Atributos de ação
A biblioteca de gerenciamento de recursos .NET é de código aberto. Para obter mais informações, visite o repositório GitHub.
Sinalizadores de recursos
Os sinalizadores de recursos são compostos por duas partes, um nome e uma lista de filtros de recursos que são usados para ativar o recurso.
Filtros de recursos
Os filtros de recursos definem um cenário para quando um recurso deve ser habilitado. Quando um recurso é avaliado se está ativado ou desativado, sua lista de filtros de recursos é percorrida até que um dos filtros decida que o recurso deve ser habilitado. Neste ponto, o recurso é considerado habilitado e atravessa os filtros de recurso para. Se nenhum filtro de recurso indicar que o recurso deve ser habilitado, ele será considerado desativado.
Como exemplo, um filtro de recurso do navegador Microsoft Edge pode ser projetado. Esse filtro de recursos ativaria todos os recursos aos quais está anexado, desde que uma solicitação HTTP seja proveniente do Microsoft Edge.
Configuração do sinalizador de recurso
O sistema de configuração .NET Core é usado para determinar o estado dos sinalizadores de recursos. A base deste sistema é IConfiguration
. Qualquer provedor para IConfiguration
pode ser usado como o provedor de estado de recurso para a biblioteca de sinalizadores de recursos. Esse sistema permite cenários que vão desde appsettings.json até a Configuração de Aplicativo do Azure e muito mais.
Declaração de Sinalizador de Funcionalidade
A biblioteca de gerenciamento de recursos suporta appsettings.json como uma fonte de sinalizador de recurso, uma vez que é um provedor para o IConfiguration
sistema do .NET Core. Abaixo temos um exemplo do formato usado para configurar sinalizadores de recursos em um arquivo 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"
}
}
]
}
}
}
A FeatureManagement
seção do documento json é usada por convenção para carregar as configurações do sinalizador de recurso. Na seção acima, vemos três características diferentes. Os recursos definem seus filtros de recursos usando a EnabledFor
propriedade. Nos filtros de recursos para FeatureT
, vemos AlwaysOn
. Esse filtro de recurso é interno e, se especificado, sempre habilitará o recurso. O AlwaysOn
filtro de recursos não requer nenhuma configuração, portanto, ele só tem a Name
propriedade. FeatureU
não tem filtros em sua EnabledFor
propriedade e, portanto, nunca será ativado. Qualquer funcionalidade que dependa da habilitação desse recurso não estará acessível enquanto os filtros de recursos permanecerem vazios. No entanto, assim que um filtro de recurso é adicionado que habilita o recurso, ele pode começar a funcionar. FeatureV
Especifica um filtro de recurso chamado TimeWindow
. Este é um exemplo de um filtro de recurso configurável. Podemos ver no exemplo que o filtro tem uma Parameters
propriedade. Isso é usado para configurar o filtro. Nesse caso, os horários de início e término para que o recurso esteja ativo são configurados.
O esquema detalhado da FeatureManagement
seção pode ser encontrado aqui.
Avançado: O uso de dois pontos ':' é proibido em nomes de sinalizadores de recursos.
Declaração On/Off
O trecho a seguir demonstra uma maneira alternativa de definir um recurso que pode ser usado para recursos ativados/desativados.
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
// Define feature flags in config file
"FeatureManagement": {
"FeatureT": true, // On feature
"FeatureX": false // Off feature
}
}
Tipo de Requisito
A RequirementType
propriedade de um sinalizador de recurso é usada para determinar se os filtros devem usar Any
ou All
lógica ao avaliar o estado de um recurso. Se RequirementType
não for especificado, o valor padrão será Any
.
Any
significa que apenas um filtro precisa ser avaliado como true para que o recurso seja habilitado.All
significa que cada filtro precisa ser avaliado como true para que o recurso seja habilitado.
A RequirementType
de All
muda a travessia. Primeiro, se não houver filtros, o recurso será desativado. Em seguida, os filtros de recurso são percorridos até que um dos filtros decida que o recurso deve ser desativado. Se nenhum filtro indicar que o recurso deve ser desativado, ele será considerado habilitado.
"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"
}
}
]
}
No exemplo acima, FeatureW
especifica a RequirementType
de All
, o que significa que todos os seus filtros devem ser avaliados como true para que o recurso seja habilitado. Nesse caso, o recurso é habilitado para 50% dos usuários durante a janela de tempo especificada.
Esquema de gerenciamento de recursos da Microsoft
A biblioteca de gerenciamento de recursos também oferece suporte ao uso de sinalizadores de Microsoft Feature Management schema
recursos para declarar. Esse esquema é independente de linguagem na origem e é suportado por todas as bibliotecas de gerenciamento de recursos da 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"
}
}
]
}
}
]
}
}
Nota
Se a feature_management
seção puder ser encontrada na configuração, a FeatureManagement
seção será ignorada.
A biblioteca de gerenciamento de recursos suporta appsettings.json como uma fonte de sinalizador de recurso, uma vez que é um provedor para o IConfiguration
sistema do .NET Core. Os sinalizadores de recursos são declarados usando o Microsoft Feature Management schema
. Esse esquema é independente de linguagem na origem e é suportado por todas as bibliotecas de gerenciamento de recursos da Microsoft.
Abaixo temos um exemplo de declaração de sinalizadores de recurso em um arquivo 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"
}
}
]
}
}
]
}
}
A feature_management
seção do documento json é usada por convenção para carregar as configurações do sinalizador de recurso. Os objetos do sinalizador de recurso devem ser listados na feature_flags
matriz na feature_management
seção . Na seção acima, vemos que fornecemos três recursos diferentes. Um sinalizador de recurso tem id
e enabled
propriedades. O id
é o nome usado para identificar e fazer referência ao sinalizador de recurso. A enabled
propriedade especifica o estado habilitado do sinalizador de recurso. Um recurso está DESATIVADO se enabled
for falso. Se enabled
for verdadeiro, então o estado do recurso depende do conditions
. Se não houverconditions
, então o recurso está ON. Se houver conditions
e eles forem atendidos, o recurso está ATIVADO. Se houver conditions
e eles não forem atendidos, o recurso é OFF. A conditions
propriedade declara as condições usadas para habilitar dinamicamente o recurso. Os recursos definem seus filtros de client_filters
recursos na matriz. FeatureV
Especifica um filtro de recurso chamado Microsoft.TimeWindow
. Este é um exemplo de um filtro de recurso configurável. Podemos ver no exemplo que o filtro tem uma Parameters
propriedade. Isso é usado para configurar o filtro. Nesse caso, os horários de início e término para que o recurso esteja ativo são configurados.
Avançado: O uso de dois pontos ':' é proibido em nomes de sinalizadores de recursos.
Tipo de Requisito
A requirement_type
propriedade de conditions
é usada para determinar se os filtros devem usar Any
ou All
lógica ao avaliar o estado de um recurso. Se requirement_type
não for especificado, o valor padrão será Any
.
Any
significa que apenas um filtro precisa ser avaliado como true para que o recurso seja habilitado.All
significa que cada filtro precisa ser avaliado como true para que o recurso seja habilitado.
A requirement_type
de All
muda a travessia. Primeiro, se não houver filtro, o recurso será desativado. Se houver filtros, os filtros de recurso serão percorridos até que um dos filtros decida que o recurso deve ser desativado. Se nenhum filtro indicar que o recurso deve ser desativado, ele será considerado habilitado.
{
"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"
}
}
]
}
}
No exemplo acima, FeatureW
especifica a requirement_type
de All
, o que significa que todos os seus filtros devem ser avaliados como true para que o recurso seja habilitado. Nesse caso, o recurso será habilitado para 50% dos usuários durante a janela de tempo especificada.
Esquema de gerenciamento de recursos do .NET
Nas versões anteriores, o esquema principal para a biblioteca de gerenciamento de recursos era o .NET feature management schema
. A partir da v4.0.0, novos recursos, incluindo variantes e telemetria, não serão suportados para o esquema de gerenciamento de recursos do .NET.
Nota
Se houver uma declaração de sinalizador de recurso que possa ser encontrada nas feature_management
seções e FeatureManagement
, a da feature_management
seção será adotada.
Consumo
A forma básica de gerenciamento de recursos é verificar se um sinalizador de recurso está habilitado e, em seguida, executar ações com base no resultado. Isto é feito através do IFeatureManager
método do .IsEnabledAsync
…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
// Do something
}
Registo de Serviços
O gerenciamento de recursos depende da injeção de dependência do .NET Core. Podemos registrar os serviços de gerenciamento de recursos usando convenções padrão.
using Microsoft.FeatureManagement;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
}
}
Por padrão, o gerenciador de recursos recupera a configuração do sinalizador de recursos da seção "FeatureManagement" dos dados de configuração do .NET Core. Se a seção "FeatureManagement" não existir, a configuração será considerada vazia.
Nota
Você também pode especificar que a configuração do sinalizador de recurso deve ser recuperada de uma seção de configuração diferente passando a seção para AddFeatureManagement
. O exemplo a seguir diz ao gerenciador de recursos para ler a partir de uma seção diferente chamada "MyFeatureFlags" em vez disso:
services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));
Injeção de Dependências
Ao usar a biblioteca de gerenciamento de recursos com MVC, o IFeatureManager
pode ser obtido por meio de injeção de dependência.
public class HomeController : Controller
{
private readonly IFeatureManager _featureManager;
public HomeController(IFeatureManager featureManager)
{
_featureManager = featureManager;
}
}
Serviços de gerenciamento de recursos com escopo
O AddFeatureManagement
método adiciona serviços de gerenciamento de recursos como singletons dentro do aplicativo, mas há cenários em que pode ser necessário que os serviços de gerenciamento de recursos sejam adicionados como serviços com escopo. Por exemplo, os usuários podem querer usar filtros de recursos que consomem serviços com escopo para informações de contexto. Neste caso, o AddScopedFeatureManagement
método deve ser usado em vez disso. Isso garante que os serviços de gerenciamento de recursos, incluindo filtros de recursos, sejam adicionados como serviços com escopo.
services.AddScopedFeatureManagement();
Integração ASP.NET Core
A biblioteca de gerenciamento de recursos fornece funcionalidade no ASP.NET Core e MVC para habilitar cenários comuns de sinalizador de recursos em aplicativos Web. Esses recursos estão disponíveis fazendo referência ao pacote NuGet Microsoft.FeatureManagement.AspNetCore .
Controladores e ações
O controlador MVC e as ações podem exigir que um determinado recurso, ou um de qualquer lista de recursos, seja habilitado para ser executado. Isso pode ser feito usando um FeatureGateAttribute
, que pode ser encontrado no Microsoft.FeatureManagement.Mvc
namespace.
[FeatureGate("FeatureX")]
public class HomeController : Controller
{
…
}
O HomeController
acima é fechado por "FeatureX". "FeatureX" deve ser ativado antes que qualquer ação que o HomeController
contém possa ser executada.
[FeatureGate("FeatureX")]
public IActionResult Index()
{
return View();
}
A Index
ação MVC acima requer que "FeatureX" seja ativado antes de poder ser executado.
Tratamento de ações desativado
Quando um controlador ou ação MVC é bloqueado porque nenhum dos recursos especificados por ele está habilitado, um registrado IDisabledFeaturesHandler
será invocado. Por padrão, um manipulador minimalista é registrado que retorna HTTP 404. Isso pode ser substituído usando os sinalizadores de recursos ao IFeatureManagementBuilder
registrar.
public interface IDisabledFeaturesHandler
{
Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}
Vista
Nas visualizações <feature>
MVC, as tags podem ser usadas para renderizar conteúdo condicionalmente com base no fato de um recurso estar habilitado ou não.
<feature name="FeatureX">
<p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
Você também pode negar a avaliação auxiliar de tag para exibir conteúdo quando um recurso ou conjunto de recursos estiver desativado. Ao definir negate="true"
no exemplo abaixo, o conteúdo só é renderizado se FeatureX
estiver desativado.
<feature negate="true" name="FeatureX">
<p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
A <feature>
tag pode fazer referência a vários recursos especificando uma lista separada por vírgulas de recursos no name
atributo.
<feature name="FeatureX,FeatureY">
<p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
Por padrão, todos os recursos listados devem ser habilitados para que a tag de recurso seja renderizada. Esse comportamento pode ser substituído adicionando o requirement
atributo como visto no exemplo abaixo.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
Nas visualizações <feature>
MVC, as tags podem ser usadas para renderizar conteúdo condicionalmente com base na habilitação de um recurso ou na atribuição de uma variante específica de um recurso. Para obter mais informações, consulte a seção variantes .
<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>
Você também pode negar a avaliação auxiliar de tag para exibir conteúdo quando um recurso ou conjunto de recursos estiver desativado. Ao definir negate="true"
no exemplo abaixo, o conteúdo só é renderizado se FeatureX
estiver desativado.
<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>
A <feature>
tag pode fazer referência a vários recursos/variantes especificando uma lista separada por vírgulas de recursos/variantes no name
/variant
atributo.
<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>
Nota
Se variant
for especificado, apenas um recurso deve ser especificado.
Por padrão, todos os recursos listados devem ser habilitados para que a tag de recurso seja renderizada. Esse comportamento pode ser substituído adicionando o requirement
atributo como visto no exemplo abaixo.
Nota
Se um requirement
for And
usado em conjunto com variant
um erro será lançado, pois várias variantes nunca podem ser atribuídas.
<feature name="FeatureX,FeatureY" requirement="Any">
<p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>
A <feature>
tag requer um auxiliar de tag para funcionar. Isso pode ser feito adicionando o auxiliar de tag de gerenciamento de recursos ao arquivo ViewImports.cshtml .
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore
Filtros MVC
Os filtros de ação MVC podem ser configurados para execução condicional com base no estado de um recurso. Isso é feito registrando filtros MVC de uma maneira ciente de recursos.
O pipeline de gerenciamento de recursos suporta filtros de ação MVC assíncronos, que implementam IAsyncActionFilter
o .
services.AddMvc(o =>
{
o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});
O código acima adiciona um filtro MVC chamado SomeMvcFilter
. Esse filtro só é acionado dentro do pipeline MVC se "FeatureX" estiver habilitado.
Razor Pages
As páginas MVC Razor podem exigir que um determinado recurso, ou um de qualquer lista de recursos, seja ativado para ser executado. Isso pode ser feito usando um FeatureGateAttribute
, que pode ser encontrado no Microsoft.FeatureManagement.Mvc
namespace.
[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
O código acima configura uma página Razor para exigir que o "FeatureX" seja ativado. Se o recurso não estiver habilitado, a página gerará um resultado HTTP 404 (NotFound).
Quando usado em páginas Razor, o FeatureGateAttribute
deve ser colocado no tipo de manipulador de página. Ele não pode ser colocado em métodos de manipulador individuais.
Construção de aplicações
A biblioteca de gerenciamento de recursos pode ser usada para adicionar ramificações de aplicativos e middleware que são executados condicionalmente com base no estado do recurso.
app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");
Com a chamada acima, o aplicativo adiciona um componente de middleware que só aparece no pipeline de solicitação se o recurso "FeatureX" estiver habilitado. Se o recurso estiver habilitado/desabilitado durante o tempo de execução, o pipeline de middleware poderá ser alterado dinamicamente.
Isso se baseia na capacidade mais genérica de ramificar todo o aplicativo com base em um recurso.
app.UseForFeature(featureName, appBuilder =>
{
appBuilder.UseMiddleware<T>();
});
Implementando um filtro de recursos
A criação de um filtro de recursos fornece uma maneira de habilitar recursos com base em critérios definidos por você. Para implementar um filtro de recursos, a IFeatureFilter
interface deve ser implementada. IFeatureFilter
tem um único método chamado EvaluateAsync
. Quando um recurso especifica que pode ser habilitado para um filtro de recurso, o EvaluateAsync
método é chamado. Se EvaluateAsync
retornar true
, significa que o recurso deve ser habilitado.
O trecho a seguir demonstra como adicionar um filtro MyCriteriaFilter
de recurso personalizado.
services.AddFeatureManagement()
.AddFeatureFilter<MyCriteriaFilter>();
Os filtros de recursos são registrados chamando AddFeatureFilter<T>
o IFeatureManagementBuilder
retorno de AddFeatureManagement
. Esses filtros de recursos têm acesso aos serviços existentes na coleção de serviços que foi usada para adicionar sinalizadores de recursos. A injeção de dependência pode ser usada para recuperar esses serviços.
Nota
Quando os filtros são referenciados nas configurações do sinalizador de recurso (por exemplo, appsettings.json), a parte Filtro do nome do tipo deve ser omitida. Para obter mais informações, consulte a Filter Alias Attribute
seção.
Filtros de recursos parametrizados
Alguns filtros de recursos exigem parâmetros para decidir se um recurso deve ser ativado ou não. Por exemplo, um filtro de recursos do navegador pode ativar um recurso para um determinado conjunto de navegadores. Pode ser desejado que os navegadores Edge e Chrome ativem um recurso, enquanto o Firefox não. Para fazer isso, um filtro de recurso pode ser projetado para esperar parâmetros. Esses parâmetros seriam especificados na configuração do recurso, e no código seria acessível através do FeatureFilterEvaluationContext
parâmetro de 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
tem uma propriedade chamada Parameters
. Esses parâmetros representam uma configuração bruta que o filtro de recursos pode usar para decidir como avaliar se o recurso deve ser habilitado ou não. Para usar o filtro de recursos do navegador como exemplo mais uma vez, o filtro poderia usar Parameters
para extrair um conjunto de navegadores permitidos que seriam especificados para o recurso e, em seguida, verificar se a solicitação está sendo enviada de um desses navegadores.
[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
}
}
Atributo de alias de filtro
Quando um filtro de recurso é registrado para um sinalizador de recurso, o alias usado na configuração é o nome do tipo de filtro de recurso com o sufixo Filtro , se houver, removido. Por exemplo, MyCriteriaFilter
seria referido como MyCriteria na configuração.
"MyFeature": {
"EnabledFor": [
{
"Name": "MyCriteria"
}
]
}
Isso pode ser substituído usando o FilterAliasAttribute
arquivo . Um filtro de recurso pode ser decorado com esse atributo para declarar o nome que deve ser usado na configuração para fazer referência a esse filtro de recurso dentro de um sinalizador de recurso.
Filtros de recursos ausentes
Se um recurso estiver configurado para ser habilitado para um filtro de recurso específico e esse filtro de recurso não estiver registrado, uma exceção será lançada quando o recurso for avaliado. A exceção pode ser desativada usando as opções de gerenciamento de recursos.
services.Configure<FeatureManagementOptions>(options =>
{
options.IgnoreMissingFeatureFilters = true;
});
Usando HttpContext
Os filtros de recursos podem avaliar se um recurso deve ser habilitado com base nas propriedades de uma solicitação HTTP. Isso é feito inspecionando o contexto HTTP. Um filtro de recurso pode obter uma referência ao contexto HTTP obtendo uma IHttpContextAccessor
injeção de dependência through.
public class BrowserFilter : IFeatureFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
public BrowserFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
}
O IHttpContextAccessor
deve ser adicionado ao contêiner de injeção de dependência na inicialização para que ele esteja disponível. Ele pode ser registrado no IServiceCollection
usando o seguinte método.
public void ConfigureServices(IServiceCollection services)
{
…
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
…
}
Avançado: IHttpContextAccessor
/HttpContext
não deve ser usado nos componentes do Razor de aplicativos Blazor do lado do servidor. A abordagem recomendada para passar o contexto http em aplicativos Blazor é copiar os dados em um serviço com escopo. Para aplicativos Blazor, AddScopedFeatureManagement
deve ser usado para registrar os serviços de gerenciamento de recursos. Para obter mais informações, consulte a Scoped Feature Management Services
seção.
Fornecer um contexto para avaliação de recursos
Em aplicativos de console, não há contexto ambiente como HttpContext
aquele que os filtros de recursos podem adquirir e utilizar para verificar se um recurso deve estar ativado ou desativado. Nesse caso, os aplicativos precisam fornecer um objeto que represente um contexto no sistema de gerenciamento de recursos para uso por filtros de recursos. Isso é feito usando IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext)
. O objeto appContext fornecido ao gerenciador de recursos pode ser usado por filtros de recursos para avaliar o estado de um recurso.
MyAppContext context = new MyAppContext
{
AccountId = current.Id;
}
if (await featureManager.IsEnabledAsync(feature, context))
{
…
}
Filtros de recursos contextuais
Filtros de recursos contextuais implementam a IContextualFeatureFilter<TContext>
interface. Esses filtros de recursos especiais podem aproveitar o contexto que é passado quando IFeatureManager.IsEnabledAsync<TContext>
é chamado. O TContext
parâmetro type em IContextualFeatureFilter<TContext>
descreve o tipo de contexto que o filtro é capaz de manipular. Isso permite que o desenvolvedor de um filtro de recurso contextual descreva o que é necessário para aqueles que desejam utilizá-lo. Como cada tipo é um descendente de objeto, um filtro que implementa IContextualFeatureFilter<object>
pode ser chamado para qualquer contexto fornecido. Para ilustrar um exemplo de um filtro de recurso contextual mais específico, considere um recurso habilitado se uma conta estiver em uma lista configurada de contas habilitadas.
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
}
}
Podemos ver que o AccountIdFilter
requer um objeto que implementa IAccountContext
a ser fornecido para ser capaz de avaliar o estado de um recurso. Ao usar esse filtro de recurso, o chamador precisa certificar-se de que o objeto passado em implementa IAccountContext
.
Nota
Apenas uma única interface de filtro de recurso pode ser implementada por um único tipo. Tentar adicionar um filtro de recurso que implementa mais de uma única interface de filtro de recurso resulta em um ArgumentException
arquivo .
Usando filtros contextuais e não contextuais com o mesmo alias
Filtra IFeatureFilter
e IContextualFeatureFilter
pode compartilhar o mesmo alias. Especificamente, você pode ter um alias de filtro compartilhado por 0 ou 1 IFeatureFilter
e 0 ou N IContextualFeatureFilter<ContextType>
, desde que haja no máximo um filtro aplicável para ContextType
.
A passagem a seguir descreve o processo de seleção de um filtro quando filtros contextuais e não contextuais do mesmo nome são registrados em um aplicativo.
Digamos que você tenha um filtro não contextual chamado FilterA
e dois filtros FilterB
contextuais e FilterC que aceitam TypeB
e TypeC
contextos, respectivamente. Todos os três filtros compartilham o mesmo alias SharedFilterName
.
Você também tem um sinalizador MyFeature
de recurso que usa o filtro SharedFilterName
de recurso em sua configuração.
Se todos os três filtros estiverem registados:
- Quando você chama IsEnabledAsync("MyFeature"), o
FilterA
é usado para avaliar o sinalizador de recurso. - Quando você chama IsEnabledAsync("MyFeature", contexto), se o tipo de contexto for
TypeB
,FilterB
é usado. Se o tipo de contexto forTypeC
,FilterC
é usado. - Quando você chama IsEnabledAsync("MyFeature", contexto), se o tipo de contexto for
TypeF
,FilterA
é usado.
Filtros de recursos integrados
Há alguns filtros de recursos que acompanham o Microsoft.FeatureManagement
pacote: PercentageFilter
, TimeWindowFilter
ContextualTargetingFilter
e TargetingFilter
. Todos os filtros, exceto o , são adicionados automaticamente quando o TargetingFilter
gerenciamento de recursos é registrado por AddFeatureManagement
método. O TargetingFilter
é adicionado com o WithTargeting
método que é detalhado na Targeting
seção abaixo.
Cada um dos filtros de recursos internos tem seus próprios parâmetros. Aqui está a lista de filtros de recursos, juntamente com exemplos.
Microsoft.Percentagem
Esse filtro fornece a capacidade de habilitar um recurso com base em uma porcentagem definida.
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.Percentage",
"Parameters": {
"Value": 50
}
}
]
}
Microsoft.TimeWindow
Esse filtro fornece a capacidade de habilitar um recurso com base em uma janela de tempo. Se apenas End
for especificado, o recurso será considerado ativado até esse momento. Se apenas Start
for especificado, o recurso será considerado ativado em todos os pontos após esse período.
"EnhancedPipeline": {
"EnabledFor": [
{
"Name": "Microsoft.TimeWindow",
"Parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
}
A janela de tempo pode ser configurada para se repetir periodicamente. Isso pode ser útil para os cenários em que pode ser necessário ativar um recurso durante um período de tráfego baixo ou alto de um dia ou certos dias de uma semana. Para expandir a janela de tempo individual para janelas de tempo recorrentes, a regra de recorrência deve ser especificada no Recurrence
parâmetro.
Nota
Start
e End
devem ser ambos especificados para habilitar Recurrence
o .
"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"
}
}
}
}
]
}
As Recurrence
configurações são compostas por duas partes: Pattern
(com que frequência a janela de tempo se repete) e Range
(por quanto tempo o padrão de recorrência se repete).
Padrão de Periodicidade
Existem dois tipos possíveis de padrões de recorrência: Daily
e Weekly
. Por exemplo, uma janela de tempo pode repetir "todos os dias", "a cada três dias", "a cada segunda-feira" ou "a cada duas sextas-feiras".
Dependendo do tipo, determinados campos do Pattern
são obrigatórios, opcionais ou ignorados.
Daily
O padrão de recorrência diária faz com que a janela de tempo se repita com base no número de dias entre cada ocorrência.
Property Relevância Description Tipo Necessário Deve ser definido como Daily
.Intervalo Opcional Especifica o número de dias entre cada ocorrência. O valor padrão é 1. Weekly
O padrão de recorrência semanal faz com que a janela de tempo se repita no mesmo dia ou dias da semana, com base no número de semanas entre cada conjunto de ocorrências.
Property Relevância Description Tipo Necessário Deve ser definido como Weekly
.Diasda Semana Necessário Especifica em quais dias da semana o evento ocorre. Intervalo Opcional Especifica o número de semanas entre cada conjunto de ocorrências. O valor padrão é 1. FirstDayOfWeek Opcional Especifica qual dia é considerado o primeiro dia da semana. O valor predefinido é Sunday
.O exemplo a seguir repete a janela de tempo a cada duas segundas e terças-feiras
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Nota
Start
deve ser uma primeira ocorrência válida que se encaixe no padrão de recorrência. Além disso, a duração da janela de tempo não pode ser maior do que a frequência com que ocorre. Por exemplo, é inválido ter uma janela de tempo de 25 horas repetida todos os dias.
Intervalo de recorrência
Existem três tipos de intervalo de recorrência possíveis: NoEnd
, EndDate
e Numbered
.
NoEnd
O
NoEnd
intervalo faz com que a recorrência ocorra indefinidamente.Property Relevância Description Tipo Necessário Deve ser definido como NoEnd
.EndDate
O
EndDate
intervalo faz com que a janela de tempo ocorra em todos os dias que se ajustam ao padrão aplicável até a data final.Property Relevância Description Tipo Necessário Deve ser definido como EndDate
.EndDate Necessário Especifica a data e hora para parar de aplicar o padrão. Desde que a hora de início da última ocorrência seja anterior à data final, a hora de fim dessa ocorrência pode estender-se para além dela. O exemplo a seguir repetirá a janela de tempo todos os dias até que a última ocorrência aconteça em 1º de abril de 2024.
"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
O
Numbered
intervalo faz com que a janela de tempo ocorra um número fixo de vezes (com base no padrão).Property Relevância Description Tipo Necessário Deve ser definido como Numbered
.NúmerodeOcorrências Necessário Especifica o número de ocorrências. O exemplo a seguir repetirá a janela de tempo na segunda e terça-feira até que haja três ocorrências, que acontecem respectivamente em 1º de abril (segunda), 2 de abril (ter) e 8 de abril (segunda).
"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 } }
Para criar uma regra de recorrência, você deve especificar e Pattern
Range
. Qualquer tipo de padrão pode funcionar com qualquer tipo de intervalo.
Avançado: O deslocamento de fuso horário da Start
propriedade é aplicado às configurações de recorrência.
Microsoft.Targeting
Esse filtro fornece a capacidade de habilitar um recurso para um público-alvo. Uma explicação detalhada da segmentação é explicada na seção de segmentação abaixo. Os parâmetros de filtro incluem um Audience
objeto que descreve usuários, grupos, usuários/grupos excluídos e uma porcentagem padrão da base de usuários que deve ter acesso ao recurso. Cada objeto de grupo listado Groups
na seção também deve especificar qual porcentagem dos membros do grupo deve ter acesso. Se um usuário for especificado na Exclusion
seção, diretamente ou se o usuário estiver em um grupo excluído, o recurso será desabilitado. Caso contrário, se um usuário for especificado na Users
seção diretamente, ou se o usuário estiver na porcentagem incluída de qualquer uma das distribuições do grupo, ou se o usuário cair na porcentagem de distribuição padrão, esse usuário terá o recurso habilitado.
"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"
]
}
}
}
}
]
}
Namespaces de alias de filtro de recursos
Todos os alias de filtro de recursos internos estão no namespace do Microsoft
filtro de recursos. Isso é para evitar conflitos com outros filtros de recursos que podem compartilhar o mesmo alias. Os segmentos de um namespace de filtro de feição são divididos pelo caractere '.' . Um filtro de recurso pode ser referenciado por seu alias totalmente qualificado, como Microsoft.Percentage
ou pelo último segmento que, no caso de Microsoft.Percentage
é Percentage
.
Seleção do destino
A segmentação é uma estratégia de gerenciamento de recursos que permite que os desenvolvedores implementem progressivamente novos recursos em sua base de usuários. A estratégia baseia-se no conceito de segmentação de um conjunto de utilizadores conhecido como público-alvo. Um público é composto por usuários específicos, grupos, usuários/grupos excluídos e uma porcentagem designada de toda a base de usuários. Os grupos que estão incluídos na audiência podem ser divididos em porcentagens de seus membros totais.
As etapas a seguir demonstram um exemplo de uma distribuição progressiva para um novo recurso 'Beta':
- Os usuários individuais Jeff e Alicia recebem acesso ao Beta
- Outro utilizador, Mark, pede para aceitar e está incluído.
- Vinte por cento de um grupo conhecido como "Ring1" usuários estão incluídos no Beta.
- O número de usuários "Ring1" incluídos na versão beta é aumentado para 100%.
- Cinco por cento da base de utilizadores está incluída na versão beta.
- A porcentagem de lançamento é aumentada para 100% e o recurso é completamente implementado.
Essa estratégia para implantar um recurso é incorporada à biblioteca por meio do filtro de recursos Microsoft.Targeting incluído.
Segmentação em um aplicativo Web
Um exemplo de aplicativo Web que usa o filtro de recurso de direcionamento está disponível no projeto de exemplo FeatureFlagDemo .
Para começar a usar o TargetingFilter
em um aplicativo, ele deve ser adicionado à coleção de serviços do aplicativo como qualquer outro filtro de recurso. Ao contrário de outros filtros internos, o TargetingFilter
depende de outro serviço para ser adicionado à coleção de serviços do aplicativo. Esse serviço é um ITargetingContextAccessor
.
Microsoft.FeatureManagement.AspNetCore
fornece uma implementação padrão da qual extrairá informações de ITargetingContextAccessor
direcionamento do HttpContext
. Você pode usar o acessador de contexto de segmentação padrão ao configurar a segmentação usando a sobrecarga não genérica WithTargeting
no IFeatureManagementBuilder
.
O acessador de contexto de segmentação padrão e TargetingFilter
são registrados chamando WithTargeting
o IFeatureManagementBuilder
.
services.AddFeatureManagement()
.WithTargeting();
Você também pode registrar uma implementação personalizada para e TargetingFilter
ligando WithTargeting<T>
para ITargetingContextAccessor
. Aqui está um exemplo de configuração do gerenciamento de recursos em um aplicativo Web para usar o TargetingFilter
com uma implementação chamada ExampleTargetingContextAccessor
ITargetingContextAccessor
.
services.AddFeatureManagement()
.WithTargeting<ExampleTargetingContextAccessor>();
ITargetingContextAccessor
Para usar o TargetingFilter
em um aplicativo Web, é necessária uma implementação de ITargetingContextAccessor
. Isso ocorre porque quando uma avaliação de segmentação está sendo realizada, informações contextuais, como qual usuário está sendo avaliado no momento, são necessárias. Esta informação é conhecida como .TargetingContext
Diferentes aplicações podem extrair essas informações de lugares diferentes. Alguns exemplos comuns de onde um aplicativo pode extrair o contexto de destino são o contexto HTTP da solicitação ou um banco de dados.
Um exemplo que extrai informações de contexto de direcionamento do contexto HTTP do aplicativo é o DefaultHttpTargetingContextAccessor
fornecido pelo Microsoft.FeatureManagement.AspNetCore
pacote. Ele extrairá informações de segmentação do HttpContext.User
. UserId
as informações serão extraídas do campo e Groups
as Identity.Name
informações serão extraídas de reivindicações do tipoRole
. Esta implementação baseia-se na utilização do , que é discutido IHttpContextAccessor
aqui.
Segmentação em um aplicativo de console
O filtro de segmentação depende de um contexto de segmentação para avaliar se um recurso deve ser ativado. Esse contexto de segmentação contém informações como qual usuário está sendo avaliado no momento e em que grupos o usuário. Em aplicativos de console, normalmente não há contexto ambiente disponível para fluir essas informações para o filtro de segmentação, portanto, elas devem ser passadas diretamente quando FeatureManager.IsEnabledAsync
são chamadas. Isso é suportado usando o ContextualTargetingFilter
. Os aplicativos que precisam flutuar o contexto de segmentação para o gerenciador de recursos devem usar isso em vez do TargetingFilter.
Uma vez que ContextualTargetingFilter
é um IContextualTargetingFilter<ITargetingContext>
, uma implementação de deve ser passada para IFeatureManager.IsEnabledAsync
que ele seja capaz de ITargetingContext
avaliar e ativar um recurso.
IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
UserId = userId,
Groups = groups
};
await fm.IsEnabledAsync(featureName, targetingContext);
O ContextualTargetingFilter
ainda usa o alias de filtro de recurso Microsoft.Targeting, portanto, a configuração para esse filtro é consistente com o que é mencionado nessa seção.
Um exemplo que usa o ContextualTargetingFilter
em um aplicativo de console está disponível no projeto de exemplo TargetingConsoleApp .
Opções de avaliação de segmentação
Estão disponíveis opções para personalizar a forma como a avaliação de segmentação é realizada em todos os recursos. Essas opções podem ser configuradas ao configurar o gerenciamento de recursos.
services.Configure<TargetingEvaluationOptions>(options =>
{
options.IgnoreCase = true;
});
Segmentação da exclusão
Ao definir um Público, os usuários e grupos podem ser excluídos do Público. Isso é útil quando um recurso está sendo implementado para um grupo de usuários, mas alguns usuários ou grupos precisam ser excluídos da distribuição. A exclusão é definida pela adição de uma lista de usuários e grupos à Exclusion
propriedade da audiência.
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
No exemplo acima, o recurso está habilitado para usuários chamados Jeff
e Alicia
. Ele também está habilitado para usuários no grupo chamado Ring0
. No entanto, se o usuário for nomeado Mark
, o recurso será desativado, independentemente de ele estar no grupo Ring0
ou não. As exclusões têm prioridade sobre o restante do filtro de segmentação.
Variantes
Quando novos recursos são adicionados a um aplicativo, pode chegar um momento em que um recurso tem várias opções de design propostas diferentes. Uma solução comum para decidir sobre um design é alguma forma de teste A/B, que envolve fornecer uma versão diferente do recurso para diferentes segmentos da base de usuários e escolher uma versão com base na interação do usuário. Nesta biblioteca, essa funcionalidade é habilitada representando diferentes configurações de um recurso com variantes.
As variantes permitem que um sinalizador de recurso se torne mais do que um simples sinalizador de ligar/desligar. Uma variante representa um valor de um sinalizador de recurso que pode ser uma cadeia de caracteres, um número, um booleano ou até mesmo um objeto de configuração. Um sinalizador de recurso que declara variantes deve definir em que circunstâncias cada variante deve ser usada, o que é abordado com mais detalhes na seção Alocação de variantes.
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; }
}
Obter variantes
Para cada recurso, uma variante pode ser recuperada usando o IVariantFeatureManager
método do 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
Uma vez que uma variante é recuperada, a configuração de uma variante pode ser usada diretamente como uma IConfigurationSection
da propriedade da variante Configuration
. Outra opção é vincular a configuração a um objeto usando . Padrão de vinculação de configuração da NET.
IConfigurationSection variantConfiguration = variant.Configuration;
MyFeatureSettings settings = new MyFeatureSettings();
variantConfiguration.Bind(settings);
A variante retornada depende do usuário que está sendo avaliado no momento, e essa informação é obtida de uma instância do TargetingContext
. Esse contexto pode ser passado ao GetVariantAsync
chamar ou pode ser recuperado automaticamente de uma implementação de ITargetingContextAccessor
se estiver registrado.
Declaração de Sinalizador de Recurso de Variante
Em comparação com os sinalizadores de recursos normais, os sinalizadores de recursos variantes têm duas propriedades adicionais: variants
e allocation
. A variants
propriedade é uma matriz que contém as variantes definidas para esse recurso. A allocation
propriedade define como essas variantes devem ser alocadas para o recurso. Assim como declarar sinalizadores de recursos normais, você pode configurar sinalizadores de recursos variantes em um arquivo json. Aqui está um exemplo de um sinalizador de recurso variante.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
Definição de variantes
Cada variante tem duas propriedades: um nome e uma configuração. O nome é usado para se referir a uma variante específica, e a configuração é o valor dessa variante. A configuração pode ser definida usando configuration_value
a propriedade. configuration_value
é uma configuração embutida que pode ser uma cadeia de caracteres, número, booleano ou objeto de configuração. Se configuration_value
não for especificado, a propriedade da variante Configuration
retornada será nula.
Uma lista de todas as variantes possíveis é definida para cada recurso sob a variants
propriedade.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
Alocação de variantes
O processo de alocação das variantes de um recurso é determinado pela allocation
propriedade do recurso.
"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"
}
]
A allocation
configuração de um recurso tem as seguintes propriedades:
Property | Description |
---|---|
default_when_disabled |
Especifica qual variante deve ser usada quando uma variante é solicitada enquanto o recurso é considerado desativado. |
default_when_enabled |
Especifica qual variante deve ser usada quando uma variante é solicitada enquanto o recurso é considerado habilitado e nenhuma outra variante foi atribuída ao usuário. |
user |
Especifica uma variante e uma lista de usuários aos quais essa variante deve ser atribuída. |
group |
Especifica uma variante e uma lista de grupos. A variante será atribuída se o usuário estiver em pelo menos um dos grupos. |
percentile |
Especifica uma variante e um intervalo de porcentagem no qual a porcentagem calculada do usuário deve se encaixar para que essa variante seja atribuída. |
seed |
O valor em percentile que se baseiam os cálculos percentuais. O cálculo de porcentagem para um usuário específico será o mesmo em todos os recursos se o mesmo seed valor for usado. Se não seed for especificado, uma semente padrão será criada com base no nome do recurso. |
No exemplo acima, se o recurso não estiver habilitado, o gerenciador de recursos atribuirá a variante marcada como default_when_disabled
ao usuário atual, que é Small
neste caso.
Se o recurso estiver habilitado, o gerenciador de recursos verificará o user
, group
e as alocações nessa ordem para atribuir uma variante percentile
. Para este exemplo em particular, se o usuário que está sendo avaliado for nomeado Marsha
, no grupo chamado Ring1
, ou se o usuário cair entre o percentil 0 e 10, a variante especificada será atribuída ao usuário. Neste caso, todos eles devolveriam a Big
variante. Se nenhuma dessas alocações corresponder, o usuário receberá a default_when_enabled
variante, que é Small
.
A lógica de alocação é semelhante ao filtro de recursos Microsoft.Targeting , mas há alguns parâmetros presentes na segmentação que não estão na alocação e vice-versa. Os resultados da segmentação e da alocação não estão relacionados.
Nota
Para permitir a alocação de variantes de recursos, você precisa se registrar ITargetingContextAccessor
. Isso pode ser feito chamando o WithTargeting<T>
método.
Substituindo o estado habilitado por uma variante
Você pode usar variantes para substituir o estado ativado de um sinalizador de recurso. Isso dá às variantes a oportunidade de estender a avaliação de um sinalizador de recurso. Ao chamar IsEnabled
um sinalizador com variantes, o gerenciador de recursos verificará se a variante atribuída ao usuário atual está configurada para substituir o resultado. Isso é feito usando a propriedade status_override
variant opcional . Por padrão, essa propriedade é definida como None
, o que significa que a variante não afeta se o sinalizador é considerado habilitado ou desabilitado. Configuração status_override
para Enabled
permitir que a variante, quando escolhida, substitua um sinalizador a ser habilitado. Configuração status_override
para Disabled
fornecer a funcionalidade oposta, portanto, desativando o sinalizador quando a variante é escolhida. Um recurso com um enabled
estado de não pode ser substituído false
.
Se você estiver usando um sinalizador de recurso com variantes binárias, a status_override
propriedade pode ser muito útil. Ele permite que você continue usando APIs como IsEnabledAsync
e FeatureGateAttribute
em seu aplicativo, enquanto se beneficia dos novos recursos que vêm com variantes, como alocação de percentil e semente.
{
"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"
}
]
}
No exemplo acima, o recurso está sempre ativado. Se o usuário atual estiver no intervalo de percentis calculado de 10 a 20, a On
variante será retornada. Caso contrário, a Off
variante é retornada e, como status_override
é igual a Disabled
, o recurso agora será considerado desativado.
Variantes na injeção de dependência
Os sinalizadores de recursos variantes podem ser usados em conjunto com a injeção de dependência para apresentar diferentes implementações de um serviço para diferentes usuários. Isso é feito usando a IVariantServiceProvider<TService>
interface.
IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...
IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken);
No trecho acima, o IVariantServiceProvider<IAlgorithm>
recupera uma implementação do contêiner de injeção de IAlgorithm
dependência. A implementação escolhida depende de:
- O sinalizador de recurso com o qual o
IAlgorithm
serviço foi registrado. - A variante alocada para esse recurso.
O IVariantServiceProvider<T>
é disponibilizado para o aplicativo ligando IFeatureManagementBuilder.WithVariantService<T>(string featureName)
para . Veja um exemplo abaixo.
services.AddFeatureManagement()
.WithVariantService<IAlgorithm>("ForecastAlgorithm");
A chamada acima é IVariantServiceProvider<IAlgorithm>
disponibilizada na coleção de serviços. As implementações de devem ser adicionadas separadamente por meio de IAlgorithm
um método add, como services.AddSingleton<IAlgorithm, SomeImplementation>()
. A implementação de que os IVariantServiceProvider
usos depende do ForecastAlgorithm
sinalizador de IAlgorithm
recurso variante. Se nenhuma implementação de for adicionada à coleção de IAlgorithm
serviços, o IVariantServiceProvider<IAlgorithm>.GetServiceAsync()
retornará uma tarefa com um resultado nulo .
{
// The example variant feature flag
"id": "ForecastAlgorithm",
"enabled": true,
"variants": [
{
"Name": "AlgorithmBeta"
},
...
]
}
Atributo de alias de serviço variante
[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
...
}
O provedor de serviços de variante usará os nomes de tipo das implementações para corresponder à variante alocada. Se um serviço de variante for decorado com o VariantServiceAliasAttribute
, o nome declarado neste atributo deve ser usado na configuração para fazer referência a esse serviço de variante.
Telemetria
Quando uma alteração de sinalizador de recurso é implantada, geralmente é importante analisar seu efeito em um aplicativo. Por exemplo, aqui estão algumas perguntas que podem surgir:
- Os meus sinalizadores estão ativados/desativados conforme esperado?
- Os usuários-alvo estão tendo acesso a um determinado recurso conforme o esperado?
- Qual variante um usuário específico está vendo?
Estes tipos de perguntas podem ser respondidas através da emissão e análise de eventos de avaliação de sinalizadores de funcionalidades. Essa biblioteca usa a API para produzir telemetria de rastreamento durante a System.Diagnostics.Activity
avaliação do sinalizador de recurso.
Habilitando a telemetria
Por padrão, os sinalizadores de recursos não têm telemetria emitida. Para publicar telemetria para um determinado sinalizador de recurso, o sinalizador DEVE declarar que está habilitado para emissão de telemetria.
Para sinalizadores de recursos definidos no appsettings.json
, isso é feito usando a telemetry
propriedade.
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
O trecho appsettings acima define um sinalizador de recurso chamado MyFeatureFlag
que está habilitado para telemetria. Isso é indicado pelo telemetry
objeto que define enabled
como true. O valor da enabled
propriedade deve ser true
publicar telemetria para o sinalizador.
A telemetry
seção de um sinalizador de recurso tem as seguintes propriedades:
Property | Description |
---|---|
enabled |
Especifica se a telemetria deve ser publicada para o sinalizador de recurso. |
metadata |
Uma coleção de pares chave-valor, modelada como um dicionário, que pode ser usada para anexar metadados personalizados sobre o sinalizador de recurso a eventos de avaliação. |
Publicação de telemetria personalizada
O gerenciador de recursos tem seu próprio ActivitySource
nome "Microsoft.FeatureManagement". Se telemetry
estiver habilitado para um sinalizador de recurso, sempre que a avaliação do sinalizador de recurso for iniciada, o gerenciador de recursos iniciará um Activity
. Quando a avaliação do sinalizador de recursos estiver concluída, o gerenciador de recursos adicionará um ActivityEvent
nome FeatureFlag
à atividade atual. O FeatureFlag
evento terá tags que incluem as informações sobre a avaliação do sinalizador de recurso, seguindo os campos definidos no esquema FeatureEvaluationEvent .
Nota
Todos os pares de valores de chave especificados no telemetry.metadata
sinalizador de recurso também serão incluídos nas tags.
Para habilitar a publicação de telemetria personalizada, você pode criar e ActivityListener
ouvir a fonte de Microsoft.FeatureManagement
atividade. Aqui está um exemplo mostrando como ouvir a fonte de atividade de gerenciamento de recursos e adicionar um retorno de chamada quando um recurso é avaliado.
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.
}
}
});
Para obter mais informações, vá para Coletar um rastreamento distribuído.
Editor de Telemetria do Application Insights
O Microsoft.FeatureManagement.Telemetry.ApplicationInsights
pacote fornece um editor de telemetria interno que envia dados de avaliação do sinalizador de recursos para o Application Insights. Para aproveitar isso, adicione uma referência ao pacote e registre o editor de telemetria do Application Insights, conforme mostrado abaixo.
builder.services
.AddFeatureManagement()
.AddApplicationInsightsTelemetryPublisher();
O Microsoft.FeatureManagement.Telemetry.ApplicationInsights
pacote fornece um inicializador de telemetria que marca automaticamente todos os eventos para TargetingId
que os eventos possam ser vinculados a avaliações de sinalizadores. Para usar o inicializador de telemetria, TargetingTelemetryInitializer
adicione-o à coleção de serviços do aplicativo.
builder.Services.AddSingleton<ITelemetryInitializer, TargetingTelemetryInitializer>();
Nota
Para garantir que TargetingTelemetryInitializer
funciona como esperado, o TargetingHttpContextMiddleware
descrito abaixo deve ser usado.
Para habilitar a persistência do contexto de segmentação na atividade atual, você pode usar o TargetingHttpContextMiddleware
.
app.UseMiddleware<TargetingHttpContextMiddleware>();
Um exemplo de seu uso pode ser encontrado no exemplo VariantAndTelemetryDemo .
Pré-requisito
Esse editor de telemetria depende de o Application Insights já estar sendo configurado registrado como um serviço de aplicativo. Por exemplo, isso é feito aqui no aplicativo de exemplo.
Esse editor de telemetria depende de o Application Insights já estar sendo configurado e registrado como um serviço de aplicativo.
Colocação em cache
O estado do IConfiguration
recurso é fornecido pelo sistema. Espera-se que qualquer cache e atualização dinâmica sejam manipulados por provedores de configuração. O gerenciador de recursos solicita IConfiguration
o valor mais recente do estado de um recurso sempre que um recurso é verificado para ser habilitado.
Instantâneo
Há cenários que exigem que o estado de um recurso permaneça consistente durante o tempo de vida de uma solicitação. Os valores retornados do padrão IFeatureManager
podem mudar se a IConfiguration
fonte da qual ele está sendo extraído for atualizada durante a solicitação. Isto pode ser evitado utilizando IFeatureManagerSnapshot
. IFeatureManagerSnapshot
pode ser recuperado da mesma forma que IFeatureManager
. IFeatureManagerSnapshot
Implementa a interface do IFeatureManager
, mas armazena em cache o primeiro estado avaliado de um recurso durante uma solicitação e retorna o mesmo estado de um recurso durante seu tempo de vida.
Provedores de recursos personalizados
A implementação de um provedor de recursos personalizado permite que os desenvolvedores extraiam sinalizadores de recursos de fontes como um banco de dados ou um serviço de gerenciamento de recursos. O provedor de recursos incluído que é usado por padrão extrai sinalizadores de recursos do sistema de configuração do .NET Core. Isso permite que os recursos sejam definidos em um arquivo de appsettings.json ou em provedores de configuração como a Configuração de Aplicativo do Azure. Esse comportamento pode ser substituído para fornecer controle completo de onde as definições de recurso são lidas.
Para personalizar o carregamento de definições de recursos, é preciso implementar a IFeatureDefinitionProvider
interface.
public interface IFeatureDefinitionProvider
{
Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);
IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}
Para usar uma implementação do , ele deve ser adicionado à coleção de serviços antes de adicionar o gerenciamento de IFeatureDefinitionProvider
recursos. O exemplo a seguir adiciona uma implementação de IFeatureDefinitionProvider
named InMemoryFeatureDefinitionProvider
.
services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
.AddFeatureManagement()
Próximos passos
Para saber como usar sinalizadores de recursos em seus aplicativos, continue para os seguintes inícios rápidos.
Para saber como usar filtros de recursos, continue para os tutoriais a seguir.
Para saber como executar experimentos com sinalizadores de recursos variantes, continue para o tutorial a seguir.