Compartilhar via


Gerenciamento de recursos do .NET

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore
Microsoft.FeatureManagement.Telemetry.ApplicationInsights

A biblioteca de gerenciamento de recursos do .NET fornece uma maneira de desenvolver e expor a funcionalidade do aplicativo com base em sinalizadores de recursos. Quando um novo recurso é desenvolvido, muitos aplicativos têm requisitos especiais, como quando o recurso deve ser habilitado e sob quais condições. Essa biblioteca fornece uma maneira de definir essas relações. Ele também se integra a padrões comuns de código .NET para tornar possível expor esses recursos.

Os sinalizadores de recursos fornecem uma maneira de os aplicativos .NET e ASP.NET Core ativarem ou desativarem os recursos dinamicamente. Você pode usar sinalizadores de recursos em casos de uso básicos, como instruções condicionais. Você também pode usar sinalizadores de recursos em cenários mais avançados, como adicionar condicionalmente rotas ou filtros MVC (model-view-controller). Os sinalizadores de recursos se baseiam no sistema de configuração do .NET Core. Qualquer provedor de configuração do .NET Core é capaz de atuar como backbone para sinalizadores de recursos.

Aqui estão alguns dos benefícios de usar a biblioteca de gerenciamento de recursos do .NET:

  • Ele usa convenções comuns para gerenciamento de recursos.
  • Ele tem uma barreira baixa à entrada:
    • Ele é criado na IConfiguration interface.
    • Ele dá suporte à configuração do sinalizador de recurso de arquivo JSON.
  • Ele fornece gerenciamento de tempo de vida do sinalizador de recursos.
    • Os valores de configuração podem ser alterados em tempo real.
    • Os sinalizadores de recursos podem ser consistentes em toda a solicitação.
  • Ele aborda cenários básicos e complexos oferecendo suporte para os seguintes recursos:
    • Ativar e desativar recursos por meio de um arquivo de configuração declarativa
    • Apresentando variantes diferentes de um recurso para usuários diferentes
    • Avaliar dinamicamente o estado de um recurso com base em uma chamada para um servidor
  • Ele fornece extensões de API para ASP.NET Core e o framework MVC nas seguintes áreas:
    • Roteamento
    • Filtros
    • Atributos de ação

A biblioteca de gerenciamento de recursos do .NET é de software livre. Para obter mais informações, consulte o repositório GitHub FeatureManagement-Dotnet .

Sinalizadores de recursos

Os sinalizadores de recursos podem ser habilitados ou desabilitados. O estado de um sinalizador pode ser condicional usando filtros de características.

Filtros de funcionalidades

Os filtros de recursos definem um cenário para quando um recurso deve ser habilitado. Para avaliar o estado de um recurso, sua lista de filtros de recursos é percorrida até que um dos filtros determine que o recurso esteja habilitado. Neste ponto, a passagem pelos filtros de recursos é interrompida. Se nenhum filtro de recurso indicar que o recurso deve ser habilitado, ele será considerado desabilitado.

Por exemplo, suponha que você projete um filtro de recurso do navegador Microsoft Edge. Se uma solicitação HTTP for proveniente do Microsoft Edge, o filtro de recursos ativará todos os recursos aos quais ele está anexado.

Configuração do sinalizador de recurso

O sistema de configuração do .NET Core é usado para determinar o estado dos sinalizadores de recursos. A base desse sistema é a IConfiguration interface. Qualquer provedor para IConfiguration pode ser usado como o provedor de estado do recurso para a biblioteca de sinalizadores de recurso. Esse sistema dá suporte a cenários que vão desde o arquivo de configuração doappsettings.json até a Configuração de Aplicativos do Azure.

Declaração do sinalizador de recurso

A biblioteca de gerenciamento de recursos dá suporte ao arquivo de configuração appsettings.json como uma fonte de sinalizador de recurso porque é um provedor para o sistema .NET Core IConfiguration . Os feature flags são declarados usando o Microsoft Feature Management schema. Este esquema é independente de linguagem de origem e tem suporte em todas as bibliotecas de gerenciamento de recursos da Microsoft.

O código no exemplo a seguir declara 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": "Sun, 01 Jun 2025 13:59:59 GMT",
                                "End": "Fri, 01 Aug 2025 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

A seção feature_management do documento JSON é usada por convenção para carregar as configurações do sinalizador de recurso. Você deve listar objetos de sinalizador de recurso na matriz feature_flags nesta seção. Esse código lista três sinalizadores de recursos. Cada objeto de sinalizador de recurso tem uma propriedade id e uma propriedade enabled.

  • O id valor é o nome que você usa para identificar e referenciar o sinalizador de recurso.
  • A propriedade enabled especifica o estado habilitado do sinalizador de recurso.

Um recurso está desativado se enabled for false. Se enabled for true, o estado do recurso dependerá da propriedade conditions. A conditions propriedade declara as condições usadas para habilitar dinamicamente o recurso.

  • Se um sinalizador de recurso não tiver uma conditions propriedade, o recurso estará ativado.
  • Se uma flag de funcionalidade tiver a propriedade conditions e suas condições forem atendidas, a funcionalidade estará ativada.
  • Se um sinalizador de recurso tiver uma propriedade conditions e suas condições não forem atendidas, o recurso estará desativado.

Os filtros de recursos são definidos na matriz client_filters. No código anterior, o sinalizador de recurso FeatureV tem um filtro de recurso chamado Microsoft.TimeWindow. Este filtro é um exemplo de um filtro de recurso configurável. Nesse código, esse filtro tem uma parameters propriedade. Esta propriedade é usada para configurar o filtro. Nesse caso, os horários de início e término do recurso a ser ativo são configurados.

Avançado: O caractere de dois-pontos (:) é proibido em nomes de sinalizador de recurso.

Tipo de Requisito

A propriedade requirement_type dentro da propriedade conditions é usada para determinar se os filtros devem usar a lógica Any ou All ao avaliar o estado de um recurso. Se requirement_type não for especificado, o valor padrão será Any. Os requirement_type valores resultam no seguinte comportamento:

  • Any: Apenas um filtro precisa resultar em true para que o recurso seja habilitado.
  • All: cada filtro precisa ser avaliado como true para que o recurso seja habilitado.

Uma requirement_type de All modifica a maneira como os filtros são percorridos:

  • Se nenhum filtro estiver listado, o recurso será desabilitado.
  • Se os filtros estiverem listados, eles serão percorridos até que as condições de um especifiquem que o recurso deve ser desabilitado. Se nenhum filtro indicar que o recurso deve ser desabilitado, ele será considerado habilitado.
{
    "id": "FeatureW",
    "enabled": true,
    "conditions": {
        "requirement_type": "All",
        "client_filters": [
            {
                "name": "Microsoft.TimeWindow",
                "parameters": {
                    "Start": "Sun, 01 Jun 2025 13:59:59 GMT",
                    "End": "Fri, 01 Aug 00:00:00 GMT"
                }
            },
            {
                "name": "Microsoft.Percentage",
                "parameters": {
                    "Value": "50"
                }
            }
        ]
    }
}

Neste exemplo, o sinalizador de recurso FeatureW tem um requirement_type com valor de All. Como resultado, todos os seus filtros devem ser avaliados como true para que o recurso seja habilitado. Nesse caso, o recurso está habilitado para 50% dos usuários durante a janela de tempo especificada.

Manipulando várias fontes de configuração

A partir da v4.3.0, você pode optar pela mesclagem personalizada para sinalizadores de recursos de esquema da Microsoft (a seção feature_management). Quando a mesma ID do sinalizador de recurso aparece em várias fontes de configuração, uma instância da classe incorporada ConfigurationFeatureDefinitionProvider mescla essas definições de acordo com a ordem de registro do provedor de configuração. Se houver um conflito, a definição do último sinalizador de recurso será usada. Esse comportamento difere da mesclagem baseada em índice de matriz padrão no .NET.

O código a seguir permite a mesclagem da configuração do sinalizador de recurso personalizado por meio da injeção de dependência:

IConfiguration configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddJsonFile("appsettings.prod.json")
    .Build();

services.AddSingleton(configuration);
services.AddFeatureManagement();
services.Configure<ConfigurationFeatureDefinitionProviderOptions>(o =>
{
        o.CustomConfigurationMergingEnabled = true;
});

Você também pode habilitar a mesclagem personalizada ao construir uma instância de ConfigurationFeatureDefinitionProvider:

var featureManager = new FeatureManager(
    new ConfigurationFeatureDefinitionProvider(
            configuration,
            new ConfigurationFeatureDefinitionProviderOptions
            {
                    CustomConfigurationMergingEnabled = true
            }));

Comportamento de exemplo:

// appsettings.json
{
    "feature_management": {
        "feature_flags": [
            { "id": "FeatureA", "enabled": true },
            { "id": "FeatureB", "enabled": false }
        ]
    }
}

// appsettings.prod.json (added later in ConfigurationBuilder)
{
    "feature_management": {
        "feature_flags": [
            { "id": "FeatureB", "enabled": true }
        ]
    }
}

Quando você habilita a mesclagem personalizada, FeatureA permanece habilitado e FeatureB resolve para habilitado, pois a última declaração é usada. Quando você usa a mesclagem padrão do .NET, em que a mesclagem personalizada é desabilitada, as matrizes são mescladas por índice. Essa abordagem poderá produzir resultados inesperados se as fontes não se alinharem por posição.

Esquema de Gerenciamento de Recursos do .NET

Nas versões anteriores da biblioteca de gerenciamento de recursos, o esquema primário era o esquema de gerenciamento de recursos do .NET.

A partir da versão 4.0.0 da biblioteca, novos recursos, incluindo variantes e telemetria, não têm suporte no esquema de gerenciamento de recursos do .NET.

Observação

Se a configuração do sinalizador de recurso incluir uma declaração listada nas seções feature_management e FeatureManagement, a que estiver na seção feature_management será adotada.

Consumo

Em uma implementação básica, o gerenciamento de recursos verifica se um sinalizador de recurso está habilitado. Em seguida, ele executa ações com base no resultado. Essa verificação é feita por meio do IsEnabledAsync método de IVariantFeatureManager.

…
IVariantFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
    // Do something.
}

Registro do serviço

O gerenciador de recursos se baseia na injeção de dependência do .NET Core. Como mostra o código a seguir, você pode usar convenções padrão para registrar serviços de gerenciamento de recursos:

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 feature_management ou FeatureManagement dos dados de configuração do .NET Core. Se nenhuma das seções existir, a configuração será considerada vazia.

Observação

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 especifica que o gerenciador de funções deve ler de uma seção chamada MyFeatureFlags em vez disso:

services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));

Injeção de dependência

Ao usar a biblioteca de gerenciamento de recursos com o MVC, você pode obter o objeto que implementa IVariantFeatureManager usando a injeção de dependência.

public class HomeController : Controller
{
    private readonly IVariantFeatureManager _featureManager;
    
    public HomeController(IVariantFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }
}

Serviços de gerenciamento de recursos com escopo

O AddFeatureManagement método adiciona serviços de gerenciamento de recursos como singletons em um aplicativo. Alguns cenários exigem que os serviços de gerenciamento de funcionalidades sejam adicionados como serviços definidos por escopo. Por exemplo, talvez você queira usar filtros de recursos que consomem serviços com escopo para obter informações de contexto. Nesse caso, você deve usar o AddScopedFeatureManagement método. Este método garante que os serviços de gerenciamento de recursos, incluindo filtros de recursos, sejam adicionados como serviços com escopo.

services.AddScopedFeatureManagement();

Integração do 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 referenciando o pacote NuGet Microsoft.FeatureManagement.AspNetCore.

Controladores e ações

Um controlador MVC e ações podem exigir que um determinado recurso ou uma de qualquer lista de recursos seja habilitado para ser executado. Você pode atender a esse requisito usando um FeatureGateAttribute objeto. A FeatureGateAttribute classe é definida no Microsoft.FeatureManagement.Mvc namespace.

[FeatureGate("FeatureX")]
public class HomeController : Controller
{
    …
}

No exemplo anterior, a HomeController classe é fechada por FeatureX. HomeController as ações só poderão ser executadas se o FeatureX recurso estiver habilitado.

[FeatureGate("FeatureX")]
public IActionResult Index()
{
    return View();
}

No exemplo anterior, a ação MVC Index só poderá ser executada se o FeatureX recurso estiver habilitado.

Manuseio de ações desabilitadas

Quando um controlador ou ação MVC é bloqueado porque nenhum dos recursos especificados está habilitado, uma implementação IDisabledFeaturesHandler registrada é invocada. Por padrão, um manipulador minimalista é registrado que retorna um erro HTTP 404. Você pode substituir esse manipulador usando IFeatureManagementBuilder ao registrar flags de funcionalidade.

public interface IDisabledFeaturesHandler
{
    Task HandleDisabledFeatures(IEnumerable<string> features, ActionExecutingContext context);
}

Visualizar

Nas views do MVC, você pode usar <feature> tags para renderizar condicionalmente o conteúdo. Você pode basear as condições de renderização em se um recurso está habilitado ou se uma variante específica de um recurso é atribuída. Para obter mais informações, consulte Variants, mais adiante neste artigo.

<feature name="FeatureX">
  <p>This content appears only when 'FeatureX' is enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha">
  <p>This content appears only when variant 'Alpha' of 'FeatureX' is assigned.</p>
</feature>

Você também pode negar a avaliação do auxiliar de marcação se quiser exibir conteúdo quando um recurso ou conjunto de recursos estiver desabilitado. Se você especificar negate="true", como nos exemplos a seguir, o conteúdo será renderizado somente quando FeatureX estiver desabilitado.

<feature negate="true" name="FeatureX">
  <p>This content appears only when 'FeatureX' is disabled.</p>
</feature>
<feature negate="true" name="FeatureX" variant="Alpha">
  <p>This content appears only when variant 'Alpha' of 'FeatureX' isn't assigned.</p>
</feature>

Você pode usar a <feature> marca para fazer referência a vários recursos. Para fazer isso, especifique uma lista separada por vírgulas de recursos no name atributo.

<feature name="FeatureX,FeatureY">
  <p>This content appears only when 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>

Por padrão, todos os recursos listados devem ser habilitados para que a marca de recurso seja renderizada. Você pode substituir esse comportamento adicionando o requirement atributo, como mostra o exemplo a seguir.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This content appears only when 'FeatureX,' 'FeatureY,' or both are enabled.</p>
</feature>

Você também pode usar a <feature> marca para fazer referência a várias variantes. Para fazer isso, use um valor requirement de Any e especifique uma lista separada por vírgulas de variantes no atributo variant.

<feature name="FeatureX" variant="Alpha,Beta" requirement="Any">
  <p>This content appears only when variant 'Alpha' or 'Beta' of 'FeatureX' is assigned.</p>
</feature>

Observação

  • Se você especificar uma variante, deverá especificar apenas um recurso.
  • Se você especificar várias variantes e usar um valor requirement de And, um erro será gerado. Você não pode atribuir várias variantes.

A marca <feature> requer que um auxiliar de marca funcione. Para usar a marca, adicione o auxiliar de marca de gerenciamento de recursos ao arquivo _ViewImports.cshtml.

@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

Filtros do MVC

Você pode configurar filtros de ação MVC que você aplica condicionalmente com base no estado de um recurso. Para configurar esses filtros, registre-os de forma consciente dos recursos. O pipeline de gerenciamento de recursos dá suporte a filtros de ação assíncronos do MVC que implementam a IAsyncActionFilter interface.

services.AddMvc(o => 
{
    o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});

O código anterior registra um filtro MVC chamado SomeMvcFilter. Esse filtro só será disparado no pipeline do MVC se FeatureX estiver habilitado.

Páginas do Razor

As páginas Razor do MVC podem exigir que um determinado recurso, ou um de qualquer lista de recursos, seja habilitado para que sejam executadas. Você pode adicionar esse requisito usando um FeatureGateAttribute objeto. A FeatureGateAttribute classe é definida no Microsoft.FeatureManagement.Mvc namespace.

[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

O código anterior configura uma página razor que requer que FeatureX esteja habilitada. Se o recurso não estiver habilitado, a página gerará um resultado HTTP 404 (NotFound).

Ao usar um objeto FeatureGateAttribute em páginas Razor, você deve definir FeatureGateAttribute no tipo de manipulador de página. Você não pode colocá-lo em métodos de manipulador individuais.

Criação de aplicativo

Você pode usar a biblioteca de gerenciamento de funcionalidades para adicionar ramificações de aplicação e middleware que são executados condicionalmente com base no estado de uma funcionalidade.

app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");

No código anterior, o aplicativo adiciona um componente de middleware que aparece no pipeline de solicitação somente se o FeatureX recurso estiver habilitado. Se o recurso estiver habilitado ou desabilitado durante o runtime, o pipeline de middleware poderá ser alterado dinamicamente.

Como mostra o código a seguir, essa funcionalidade cria a funcionalidade mais genérica para ramificar todo o aplicativo com base em um recurso.

app.UseForFeature(featureName, appBuilder => 
{
    appBuilder.UseMiddleware<T>();
});

Implementar um filtro de funcionalidades

A criação de um filtro de recursos fornece uma maneira de habilitar recursos com base nos critérios definidos por você. Para implementar um filtro de recurso, você deve implementar a IFeatureFilter interface. IFeatureFilter tem um único método chamado EvaluateAsync. Quando um recurso especifica que ele pode ser habilitado para um filtro de recurso, o método EvaluateAsync é chamado. Se EvaluateAsync retornar true, significa que o recurso deve ser habilitado.

O código a seguir demonstra como adicionar um filtro de recurso personalizado chamado MyCriteriaFilter.

services.AddFeatureManagement()
        .AddFeatureFilter<MyCriteriaFilter>();

Você pode registrar um filtro de recurso chamando AddFeatureFilter<T> na implementação IFeatureManagementBuilder retornada por AddFeatureManagement. O filtro de recurso tem acesso aos serviços na coleção de serviços que você usa para adicionar sinalizadores de recursos. Você pode usar a injeção de dependência para recuperar esses serviços.

Observação

Ao referenciar filtros nas configurações do sinalizador de recurso (por exemplo, appsettings.json), você deve omitir a Filter parte do nome do tipo. Para obter mais informações, consulte o atributo de alias Filter, mais adiante neste artigo.

Filtros de recursos parametrizados

Alguns filtros de recurso exigem parâmetros para avaliar se um recurso deve ser ativado. Por exemplo, um filtro de recurso do navegador pode ativar um recurso para um determinado conjunto de navegadores. Talvez você queira ativar um recurso nos navegadores Microsoft Edge e Chrome, mas não no Firefox.

Para implementar essa filtragem, você pode criar um filtro de funcionalidades que aceite parâmetros. Especifique esses parâmetros na configuração do recurso. No código, você os acessa usando o parâmetro FeatureFilterEvaluationContext 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; }
}

A FeatureFilterEvaluationContext classe tem uma propriedade chamada Parameters. Os parâmetros dessa propriedade representam uma configuração bruta que o filtro de recurso pode usar ao avaliar se o recurso deve ser habilitado. No exemplo de filtro de recurso do navegador, o filtro pode usar a Parameters propriedade para extrair um conjunto de navegadores permitidos especificados para o recurso. O filtro pode verificar se a solicitação é de um desses navegadores.

[FilterAlias("Browser")]
public class BrowserFilter : IFeatureFilter
{
    …

    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
    {
        BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();

        //
        // Use the settings to check whether the request is from a browser in BrowserFilterSettings.AllowedBrowsers.
    }
}

Filtrar atributo de alias

Quando você registra um filtro de funcionalidade para um sinalizador de funcionalidade, o alias que você usa na configuração é o nome do tipo de filtro de funcionalidade, com o sufixo Filter removido, se houver. Por exemplo, você deve se referir a MyCriteriaFilter como MyCriteria na configuração.

{
    "id": "MyFeature",
    "enabled": true,
    "conditions": {
        "client_filters": [
            {
                "name": "MyCriteria"
            }
        ]
    }
}

Você pode substituir esse nome usando a FilterAliasAttribute classe. Para declarar um nome a ser usado na configuração para fazer referência a um filtro de recurso dentro de um sinalizador de recurso, você pode decorar o filtro de recursos com esse atributo.

Filtros para funcionalidades ausentes

Suponha que você configure um recurso a ser habilitado para um filtro de recurso específico. Se esse filtro de recurso não estiver registrado, uma exceção será gerada quando o recurso for avaliado. Como mostra o código a seguir, você pode desabilitar a exceção usando opções de gerenciamento de recursos.

services.Configure<FeatureManagementOptions>(options =>
{
    options.IgnoreMissingFeatureFilters = true;
});

Usar HttpContext

Os filtros de recursos podem avaliar se um recurso deve ser habilitado com base nas propriedades de uma solicitação HTTP. Essa verificação é executada inspecionando o contexto HTTP. Como mostra o código a seguir, um filtro de funcionalidade pode obter uma referência ao contexto HTTP usando a injeção de dependência para obter uma implementação de IHttpContextAccessor.

public class BrowserFilter : IFeatureFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BrowserFilter(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }
}

Você deve adicionar a IHttpContextAccessor implementação ao contêiner de injeção de dependência na inicialização para que ele esteja disponível. Você pode usar o método a seguir para registrar a implementação nos IServiceCollection serviços.

public void ConfigureServices(IServiceCollection services)
{
    …
    services.AddHttpContextAccessor();
    …
}

Avançado:IHttpContextAccessor e HttpContext não devem ser usados nos componentes Razor de aplicativos Blazor do lado do servidor. A abordagem recomendada para passar o contexto HTTP em aplicativos Blazor é copiar os dados para um serviço com escopo definido. Para aplicativos Blazor, você deve usar AddScopedFeatureManagement para registrar serviços de gerenciamento de recursos. Para obter mais informações, consulte Serviços de gerenciamento de recursos com escopo, anteriormente neste artigo.

Fornecer um contexto para avaliação de funcionalidades

Em aplicativos de console, não há nenhum contexto ambiente, como HttpContext, que os filtros de funcionalidades podem usar para verificar se um recurso deve estar ativado. Nesse caso, os aplicativos precisam fornecer um objeto que represente um contexto para o sistema de gerenciamento de recursos para uso por filtros de recursos. Você pode usar IVariantFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext) para fornecer esse contexto. Para avaliar o estado de um recurso, os filtros de recursos podem usar o appContext objeto que você fornece ao gerenciador de recursos.

MyAppContext context = new MyAppContext
{
    AccountId = current.Id
};

if (await featureManager.IsEnabledAsync(feature, context))
{
…
}

Filtros de características contextuais

Os filtros de recursos contextuais implementam a interface IContextualFeatureFilter<TContext>. Esses filtros de recursos especiais podem aproveitar o contexto passado quando IVariantFeatureManager.IsEnabledAsync<TContext> é chamado. O parâmetro de tipo TContext em IContextualFeatureFilter<TContext> descreve o tipo de contexto que o filtro pode manipular. Ao desenvolver um filtro de recurso contextual, você pode estabelecer os requisitos para usar o filtro especificando um tipo de contexto.

Como cada tipo é um descendente da Object classe, um filtro que implementa IContextualFeatureFilter<object> pode ser chamado para qualquer contexto fornecido. O código a seguir fornece um exemplo de um filtro de recurso contextual específico. Nesse código, um recurso será 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 whether the feature should be on by using the IAccountContext that's provided.
    }
}

A AccountIdFilter classe requer que um objeto que implementa IAccountContext seja fornecido para ser capaz de avaliar o estado de um recurso. Quando você usa esse filtro de funcionalidade, o chamador precisa assegurar-se de que o objeto passado implemente IAccountContext.

Observação

Somente uma única interface de filtro de recurso pode ser implementada por um único tipo. Tentar adicionar um filtro de funcionalidade que implementa mais de uma interface de filtro de funcionalidade resulta em uma exceção ArgumentException.

Usar filtros contextuais e não contextuais com o mesmo alias

Filtra que implementa IFeatureFilter e IContextualFeatureFilter pode compartilhar o mesmo alias. Especificamente, você pode ter um alias de filtro compartilhado por zero ou uma IFeatureFilter implementações e zero ou NIContextualFeatureFilter<ContextType> implementações se houver no máximo um filtro aplicável para ContextType.

Para entender o processo de seleção de um filtro quando filtros contextuais e não contextuais de mesmo nome forem registrados em um aplicativo, considere o exemplo a seguir.

Três filtros compartilham o alias SharedFilterName :

  • Um filtro não contextual chamado FilterA
  • Um filtro contextual chamado FilterB que aceita um TypeB contexto
  • Um filtro contextual chamado FilterC que aceita um TypeC contexto

Um sinalizador de recurso chamado MyFeature usa o filtro de recurso SharedFilterName em sua configuração.

Se todos os três filtros estiverem registrados:

  • Quando você chama IsEnabledAsync("MyFeature"), o filtro FilterA é usado para avaliar o sinalizador de recurso.
  • Quando você chama IsEnabledAsync("MyFeature", context):
    • Se o tipo de context for TypeB, FilterB será usado.
    • Se o tipo de context for TypeC, FilterC será usado.
    • Se o tipo do context é TypeF, FilterA é usado.

Filtros de funções integradas

Há alguns filtros de recursos que vêm com o pacote: Microsoft.FeatureManagement, PercentageFilter, TimeWindowFilter, ContextualTargetingFilter e TargetingFilter. Todos os filtros exceto TargetingFilter são adicionados automaticamente quando você usa o método para registrar o AddFeatureManagement gerenciamento de recursos. TargetingFilter é adicionado usando o WithTargeting método. Para obter mais informações, consulte Direcionamento, mais adiante neste artigo.

Cada um dos filtros de recursos internos tem seus próprios parâmetros. As seções a seguir descrevem esses filtros de recursos e fornecem exemplos.

Microsoft.Percentage

O Microsoft.Percentage filtro fornece uma maneira de habilitar um recurso com base em uma porcentagem definida.

{
    "id": "EnhancedPipeline",
    "enabled": true,
    "conditions": {
        "client_filters": [
            {
                "name": "Microsoft.Percentage",
                "parameters": {
                    "Value": 50
                }
            }
        ]
    }
}

Microsoft.TimeWindow

O Microsoft.TimeWindow filtro fornece uma maneira de habilitar um recurso com base em uma janela de tempo.

  • Se você especificar apenas um End valor, o recurso será considerado ativado até esse momento.
  • Se você especificar apenas um valor Start, o recurso será considerado ativo em todos os momentos a partir desse momento.
{
    "id": "EnhancedPipeline",
    "enabled": true,
    "conditions": {
        "client_filters": [
            {
                "name": "Microsoft.TimeWindow",
                "parameters": {
                    "Start": "Sun, 01 Jun 2025 13:59:59 GMT",
                    "End": "Fri, 01 Aug 2025 00:00:00 GMT"
                }
            }
        ]
    }
}

Você pode configurar o filtro para aplicar uma janela de tempo de forma recorrente. Essa funcionalidade pode ser útil quando você precisa ativar um recurso durante um período de tráfego baixo ou alto de um dia ou determinados dias de uma semana. Para expandir uma janela de tempo individual para uma janela de tempo recorrente, use um Recurrence parâmetro para especificar uma regra de recorrência.

Observação

Para usar a recorrência, você deve especificar Start e End valores. Com a recorrência, a parte de data do valor End não especifica uma data de término para que o filtro seja considerado ativo. Em vez disso, o filtro usa a data de término, em relação à data de início, para definir a duração da janela de tempo que se repetirá.

{
    "id": "EnhancedPipeline",
    "enabled": true,
    "conditions": {
        "client_filters": [
            {
                "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:

  • As Pattern configurações especificam a frequência com que a janela de tempo se repete.
  • As Range configurações especificam por quanto tempo o padrão de recorrência se repete.

Padrão de recorrência

Há dois tipos de padrão de recorrência possíveis: Daily e Weekly. Por exemplo, uma janela de tempo pode se repetir todos os dias, a cada três dias, todas as segundas-feiras ou todas as outras sextas-feiras.

Dependendo do tipo, determinados campos das Pattern configurações são necessários, opcionais ou ignorados.

  • Daily

    O padrão de recorrência diária faz com que a janela de tempo se repita com base em um número especificado de dias entre cada ocorrência.

    Propriedade Relevância Descrição
    Type Obrigatório O tipo de padrão de recorrência. Deve ser definido como Daily.
    Interval Opcional 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. Mas você pode especificar o número de semanas entre cada conjunto de ocorrências.

    Propriedade Relevância Descrição
    Type Obrigatório O tipo de padrão de recorrência. Deve ser definido como Weekly.
    DaysOfWeek Obrigatório Os dias da semana em que o evento ocorre.
    Interval Opcional O número de semanas entre cada conjunto de ocorrências. O valor padrão é 1.
    FirstDayOfWeek Opcional O dia a ser usado como o primeiro dia da semana. O valor padrão é Sunday.

    O exemplo a seguir repete a janela de tempo a cada segunda e terça-feira:

    "Pattern": {
        "Type": "Weekly",
        "Interval": 2,
        "DaysOfWeek": ["Monday", "Tuesday"]
    }
    

Observação

O Start valor deve ser uma primeira ocorrência válida que se ajuste ao 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 ela ocorre. Por exemplo, uma janela de tempo de 25 horas não pode se repetir todos os dias.

Intervalo de recorrência

Há três tipos de intervalo de recorrência possíveis: NoEnd, EndDatee Numbered.

  • NoEnd

    O intervalo NoEnd faz com que a recorrência ocorra indefinidamente.

    Propriedade Relevância Descrição
    Type Obrigatório O tipo de intervalo de recorrência. Deve ser definido como NoEnd.
  • EndDate

    O intervalo EndDate faz com que a janela de tempo ocorra em todos os dias que se ajustem ao padrão aplicável até a data de término.

    Propriedade Relevância Descrição
    Type Obrigatório O tipo de intervalo de recorrência. Deve ser definido como EndDate.
    EndDate Obrigatório A data e a hora para parar de aplicar o padrão. Se a hora de início da última ocorrência cair antes da data de término, a hora de término dessa ocorrência poderá se estender além dela.

    No exemplo a seguir, a janela de tempo se repete todos os dias até a última ocorrência 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 especificado de vezes.

    Propriedade Relevância Descrição
    Type Obrigatório O tipo de intervalo de recorrência. Deve ser definido como Numbered.
    NumberOfOccurrences Obrigatório O número de ocorrências.

    No exemplo a seguir, a janela de tempo se repete na segunda e na terça-feira para um total de três ocorrências, que ocorrem nas seguintes datas:

    • Segunda-feira, 1º de abril
    • Terça-feira, 2 de abril
    • Segunda-feira, 8 de abril
    "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 ambas as PatternRange configurações. Qualquer tipo de padrão pode funcionar com qualquer tipo de intervalo.

Avançado: o deslocamento de fuso horário da propriedade Start é aplicado às configurações de recorrência.

Microsoft.Targeting

O Microsoft.Targeting filtro fornece uma maneira de habilitar um recurso para um público-alvo. Para obter uma explicação detalhada do direcionamento, consulte Targeting, mais adiante neste artigo.

Os parâmetros de filtro incluem um Audience objeto que descreve quem tem acesso ao recurso. Dentro do Audience objeto, você pode especificar usuários, grupos, usuários e grupos excluídos e um percentual padrão da base de usuários.

Para cada objeto de grupo listado na Groups seção, você também deve especificar qual porcentagem dos membros do grupo deve ter acesso.

Para cada usuário, o recurso é avaliado da seguinte maneira:

  • Se o usuário for excluído, o recurso será desabilitado para o usuário. Você pode excluir o usuário por:

    • Listando seu nome em Users na seção Exclusion.
    • Listando um grupo a que pertencem em Groups na seção Exclusion.
  • Se o usuário não for excluído, o recurso será habilitado se qualquer uma das seguintes condições for atendida:

    • O usuário está listado na Users seção.
    • O usuário está na porcentagem incluída de qualquer uma das distribuições de grupo.
    • O usuário se enquadra na porcentagem de implantação padrão.
  • Se nenhum dos casos anteriores se aplicar, o recurso será desabilitado para o usuário. Por exemplo, se o usuário não estiver em uma porcentagem incluída, o recurso será desabilitado.

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

Namespaces de alias de funcionalidades de filtro

Todos os alias de filtro de função internos estão no namespace do filtro de função Microsoft. Estar nesse namespace impede conflitos com outros filtros de recurso que compartilham o mesmo alias. Os segmentos de um namespace de filtro de recurso são divididos pelo caractere .. Você pode referenciar um filtro de funcionalidade por seu alias totalmente qualificado, como Microsoft.Percentage. Ou você pode referenciar o último segmento, como Percentage.

Direcionamento

O direcionamento é uma estratégia de gerenciamento de recursos que você pode usar para distribuir progressivamente novos recursos para sua base de usuários. A estratégia baseia-se no conceito de atingir um conjunto de usuários conhecido como público-alvo. Uma audiência é composta por usuários específicos, grupos, usuários e grupos excluídos e um percentual designado de toda a base de usuários. Os grupos incluídos na audiência podem ser divididos ainda mais em percentuais de seus membros totais.

As etapas a seguir demonstram um exemplo de uma distribuição progressiva para um novo recurso chamado Beta:

  1. Usuários individuais Jeff e Alicia recebem acesso ao recurso Beta.
  2. Outro usuário, Mark, pede para aceitar e é incluído.
  3. Vinte por cento dos usuários do grupo Ring1 estão incluídos no recurso Beta.
  4. O número de usuários do Ring1 incluídos é aumentado para 100%.
  5. Cinco por cento da base de usuários está incluída no recurso Beta.
  6. O percentual de distribuição é aumentado em até 100% para distribuir completamente o recurso.

A biblioteca dá suporte a essa estratégia para distribuir um recurso por meio do filtro de funcionalidades embutido Microsoft.Targeting.

Segmentação em um aplicativo web

Para obter um exemplo de um aplicativo Web que usa o filtro de recurso de direcionamento, consulte o projeto de exemplo FeatureFlagDemo .

Para começar a usar TargetingFilter em um aplicativo, você deve adicioná-lo à coleção de serviços do aplicativo, assim como qualquer outro filtro de recurso. Ao contrário de outros filtros internos, TargetingFilter depende de outro serviço a ser adicionado à coleção de serviços do aplicativo. Esse serviço é uma implementação ITargetingContextAccessor .

A biblioteca Microsoft.FeatureManagement.AspNetCore fornece uma implementação padrão de ITargetingContextAccessor que extrai informações de direcionamento do valor de uma solicitação 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 em IFeatureManagementBuilder.

Para registrar o acessador de contexto de direcionamento padrão e TargetingFilter, você chama WithTargeting em IFeatureManagementBuilder.

services.AddFeatureManagement()
        .WithTargeting();

Você também pode registrar uma implementação personalizada para ITargetingContextAccessor e TargetingFilter chamando WithTargeting<T>. O código a seguir configura o gerenciamento de recursos em um aplicativo Web para usar TargetingFilter com uma implementação de ITargetingContextAccessor chamada ExampleTargetingContextAccessor.

services.AddFeatureManagement()
        .WithTargeting<ExampleTargetingContextAccessor>();

ITargetingContextAccessor

Para usar TargetingFilter em um aplicativo da web, é necessária uma implementação de ITargetingContextAccessor. O raciocínio por trás desse requisito é que informações contextuais, como informações sobre o usuário, são necessárias para direcionar avaliações. Essas informações são armazenadas em instâncias da TargetingContext classe. Aplicativos diferentes extraem essas informações de locais diferentes, como o contexto HTTP de uma solicitação ou um banco de dados.

Para obter um exemplo que extrai informações de contexto de direcionamento do contexto HTTP de um aplicativo, consulte DefaultHttpTargetingContextAccessor no pacote Microsoft.FeatureManagement.AspNetCore. Ele extrai as seguintes informações:

  • Direcionando informações da propriedade HttpContext.User
  • UserId informações do campo Identity.Name
  • Groups informações de declarações do tipo Role

Essa implementação depende do uso de IHttpContextAccessor. Para obter mais informações sobre IHttpContextAccessor, consulte Usar HttpContext, anteriormente neste artigo.

Direcionamento em um aplicativo de console

O filtro de direcionamento depende de um contexto de direcionamento para avaliar se um recurso deve ser ativado. Esse contexto de direcionamento contém informações como o usuário que está sendo avaliado e os grupos aos quais o usuário pertence. Em aplicativos de console, normalmente não há nenhum contexto ambiente disponível para passar essas informações para o filtro de destino. Como resultado, você deve passá-lo diretamente quando chamar FeatureManager.IsEnabledAsync. Esse tipo de contexto tem suporte usando ContextualTargetingFilter. Os aplicativos que precisam enviar o contexto de direcionamento para o gerenciador de funcionalidades devem usar ContextualTargetingFilter em vez de TargetingFilter.

Como ContextualTargetingFilter implementa IContextualTargetingFilter<ITargetingContext>, você deve passar uma implementação ITargetingContext para IVariantFeatureManager.IsEnabledAsync que ele possa avaliar e ativar um recurso.

IVariantFeatureManager fm;
…
// The userId and groups variables are defined earlier in the application.
TargetingContext targetingContext = new TargetingContext
{
   UserId = userId,
   Groups = groups
};

await fm.IsEnabledAsync(featureName, targetingContext);

ContextualTargetingFilter usa o alias Microsoft.Targetingde filtro de recurso, portanto, a configuração desse filtro é consistente com as informações em Microsoft.Targeting, anteriormente neste artigo.

Para obter um exemplo que usa ContextualTargetingFilter em um aplicativo de console, consulte o projeto de exemplo TargetingConsoleApp .

Opções de avaliação de direcionamento

As opções estão disponíveis para personalizar como a avaliação de direcionamento é executada em todos os recursos. Você pode configurar essas opções ao configurar o gerenciamento de recursos.

services.Configure<TargetingEvaluationOptions>(options =>
{
    options.IgnoreCase = true;
});

Exclusão de direcionamento

Ao definir uma audiência, você pode excluir usuários e grupos da audiência. Essa funcionalidade é útil quando você distribui um recurso para um grupo de usuários, mas precisa excluir alguns usuários ou grupos da distribuição. Para especificar usuários e grupos a serem excluídos, use a Exclusion propriedade do público.

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

O código anterior habilita um recurso para usuários nomeados Jeff e Alicia. O recurso também está habilitado para usuários no grupo chamado Ring0. No entanto, o recurso está desabilitado para o usuário nomeado Mark, mesmo que esse usuário esteja no Ring0 grupo. As exclusões têm prioridade sobre o restante do filtro de direcionamento.

Variantes

Às vezes, quando você adiciona um novo recurso a um aplicativo, o recurso tem várias opções de design propostas. O teste A/B fornece uma solução comum para decidir sobre um design. O teste A/B envolve fornecer uma versão diferente do recurso para diferentes segmentos da base de usuários e, em seguida, escolher uma versão com base na interação do usuário. Na biblioteca de gerenciamento de recursos do .NET, você pode implementar testes A/B usando variantes para representar várias configurações de um recurso.

As variantes fornecem uma maneira de um sinalizador de recurso se tornar mais do que um sinalizador de ativação/desativação básico. Uma variante representa um valor de um sinalizador de recurso que pode ser uma cadeia de caracteres, um número, um booliano ou até mesmo um objeto de configuração. Um sinalizador de recurso que declara variantes deve definir as circunstâncias em que cada variante deve ser usada. Para obter mais informações, consulte Alocar variantes, mais adiante neste artigo.

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; }
}

Recuperar variantes

Para cada recurso, você pode recuperar uma variante usando o GetVariantAsync método da IVariantFeatureManager interface.

…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync("MyVariantFeatureFlag", CancellationToken.None);

IConfigurationSection variantConfiguration = variant.Configuration;

// Do something with the resulting variant and its configuration.

Depois de recuperar uma variante, você pode usar a configuração dela diretamente como uma implementação de IConfigurationSection a partir da propriedade Configuration da variante. Outra opção é associar a configuração a um objeto usando o padrão de associação de configuração do .NET.

IConfigurationSection variantConfiguration = variant.Configuration;

MyFeatureSettings settings = new MyFeatureSettings();

variantConfiguration.Bind(settings);

A variante retornada depende do usuário que está sendo avaliado. Você pode obter informações sobre o usuário de uma instância de TargetingContext. Você pode passar esse contexto ao chamar GetVariantAsync. Ou pode ser recuperado automaticamente de uma implementação de ITargetingContextAccessor se um estiver registrado.

Declaração do sinalizador de recurso variante

Em comparação com os sinalizadores de recursos padrão, os sinalizadores de recursos variantes têm duas propriedades extras: variants e allocation. A variants propriedade é uma matriz que contém as variantes definidas para o recurso. A propriedade allocation define como essas variantes devem ser alocadas para o recurso. Assim como declarar sinalizadores de recursos padrão, você pode configurar sinalizadores de recursos variantes em um arquivo JSON. O código a seguir é 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"
                    } 
                ]
            }
        ]
    }
}

Definir 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. Você pode usar a configuration_value propriedade para especificar a configuração. A configuration_value propriedade é uma configuração embutida que pode ser uma cadeia de caracteres, número, booliano ou objeto de configuração. Se você não configurar a configuration_value propriedade, a propriedade da Configuration variante retornada será null.

Para especificar todas as variantes possíveis para um recurso, você as lista na variants propriedade.

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

Alocar variantes

Para alocar as variantes de um recurso, use a 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 tem as seguintes propriedades:

Propriedade Descrição
default_when_disabled A variante a ser usada quando uma variante é solicitada enquanto o recurso é considerado desabilitado.
default_when_enabled A variante a ser usada quando uma variante é solicitada enquanto o recurso é considerado habilitado e nenhuma outra variante é atribuída ao usuário.
user Uma variante e uma lista de usuários aos quais atribuir a variante.
group Uma variante e uma lista de grupos. A variante será atribuída se o usuário atual estiver em pelo menos um dos grupos.
percentile Uma variante e um intervalo de porcentagem nos quais o percentual calculado do usuário precisa se ajustar para que a variante seja atribuída.
seed O valor no qual os cálculos de porcentagem para percentile se baseiam. 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 nenhum seed valor for especificado, uma semente padrão será criada com base no nome do recurso.

Se um recurso não estiver habilitado, o gerenciador de recursos atribuirá a variante especificada para default_when_disabled ao usuário atual. No exemplo anterior, esse recurso é chamado Small.

Se o recurso estiver habilitado, o gerente de recursos verificará as alocações user, group e percentile nessa ordem para atribuir uma variante. No exemplo anterior, a variante Bigespecificada é atribuída ao usuário nos seguintes casos:

  • O usuário que está sendo avaliado é nomeado Marsha.
  • O usuário está no grupo Ring1.
  • Acontece que o usuário fica entre o zero e o décimo percentil.

Se nenhuma dessas alocações corresponder, a default_when_enabled variante será atribuída ao usuário. No exemplo, essa variante é Small.

A lógica de alocação é semelhante à lógica usada para o filtro de recursos Microsoft.Targeting . Mas há alguns parâmetros presentes no direcionamento que não estão na alocação e vice-versa. Os resultados de direcionamento e alocação não estão relacionados.

Observação

Para alocar variantes de funcionalidades, você precisa se registrar ITargetingContextAccessor chamando o método WithTargeting<T>.

Substituir o estado habilitado usando uma variante

Você pode usar variantes para substituir o estado habilitado de um sinalizador de recurso. Ao aproveitar essa funcionalidade, você pode estender a avaliação de um sinalizador de recurso. Durante a chamada para IsEnabledAsync em um sinalizador com variantes, o gerenciador de funcionalidades verifica se a variante destinada ao usuário atual está configurada para sobrescrever o resultado.

Você pode implementar a substituição usando a propriedade de variante opcional status_override. Essa propriedade pode ter os seguintes valores:

  • None: a variante não afeta se o sinalizador é considerado habilitado ou desabilitado. None é o valor padrão.
  • Enabled: quando a variante é escolhida, o sinalizador de recurso é avaliado como habilitado.
  • Disabled: quando a variante é escolhida, o sinalizador de recurso é avaliado como desabilitado.

Você não pode substituir um recurso com um estado enabled de false.

Se você usar um sinalizador de recurso com variantes binárias, a status_override propriedade poderá ser útil. Você pode continuar a usar APIs como IsEnabledAsync e FeatureGateAttribute em seu aplicativo. Mas você também pode se beneficiar dos recursos que vêm com variantes, como distribuição percentílica e uso de um valor inicial para cálculos percentuais.

{
    "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 anterior, o recurso está sempre habilitado. Se o usuário atual estiver no intervalo de percentil calculado de 10 a 20, a On variante será retornada. Caso contrário, a Off variante será retornada e, como o status_override valor é Disabled, o recurso será considerado desabilitado.

Variantes na injeção de dependência

Você pode usar sinalizadores de recursos variantes junto com a injeção de dependência para expor diferentes implementações de um serviço a usuários diferentes. A IVariantServiceProvider<TService> interface fornece uma maneira de realizar essa combinação.

IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...

IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken); 

No código anterior, a implementação IVariantServiceProvider<IAlgorithm> recupera uma implementação de IAlgorithm do contêiner de injeção de dependência. A implementação escolhida depende de:

  • O sinalizador de função com que o serviço IAlgorithm está registrado.
  • A variante alocada para esse recurso.

A IVariantServiceProvider<T> implementação é disponibilizada para o aplicativo chamando IFeatureManagementBuilder.WithVariantService<T>(string featureName), como mostra o exemplo a seguir. A chamada nesse código disponibiliza IVariantServiceProvider<IAlgorithm> na coleção de serviços.

services.AddFeatureManagement() 
        .WithVariantService<IAlgorithm>("ForecastAlgorithm");

Você deve adicionar cada implementação de IAlgorithm separadamente, por meio de um método de adição, como services.AddSingleton<IAlgorithm, SomeImplementation>(). A implementação de IAlgorithm que IVariantServiceProvider usa depende do sinalizador de variante de recurso ForecastAlgorithm. Se nenhuma implementação de IAlgorithm for adicionada à coleção de serviços, IVariantServiceProvider<IAlgorithm>.GetServiceAsync() retornará uma tarefa com um null resultado.

{
    // The example variant feature flag
    "id": "ForecastAlgorithm",
    "enabled": true,
    "variants": [
        { 
            "Name": "AlgorithmBeta" 
        },
        ...
    ] 
}

Atributo de alias de serviço variável

O provedor de serviços variante usa os nomes de tipo de implementações para corresponder à variante alocada. Se um serviço variante for decorado com VariantServiceAliasAttribute, o nome declarado nesse atributo deverá ser usado na configuração para referenciar esse serviço variante.

[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
    ...
}

Telemetria

Quando você implanta uma alteração de sinalizador de recurso, geralmente é importante analisar seu efeito em um aplicativo. Por exemplo, aqui estão algumas perguntas que podem surgir:

  • Os sinalizadores estão habilitados e desabilitados conforme o esperado?
  • Os usuários direcionados estão recebendo acesso a um determinado recurso conforme o esperado?
  • Qual variante um usuário específico vê?

A emissão e a análise de eventos de avaliação de feature flags podem ajudá-lo a responder a esses tipos de perguntas. A biblioteca de gerenciamento de funcionalidades do .NET usa a API System.Diagnostics.Activity para produzir telemetria de rastreamento durante a avaliação do sinalizador de funcionalidade.

Habilitar telemetria

Por padrão, os sinalizadores de recursos não têm telemetria emitida. Para publicar a telemetria de um determinado sinalizador de recurso, o sinalizador deve declarar que ele está habilitado para emissão de telemetria.

Para flags de recursos definidos em appsettings.json, você pode habilitar a telemetria usando a propriedade telemetry.

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

O código anterior de um arquivo appsettings.json define um sinalizador de recurso chamado MyFeatureFlag habilitado para telemetria. O estado de telemetria é indicado pelo telemetry objeto que define enabled como true. O valor da propriedade enabled deve ser true para publicar telemetria para o sinalizador.

A seção telemetry de um sinalizador de recurso tem as seguintes propriedades:

Propriedade Descrição
enabled Um valor booliano que 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 você pode usar para anexar metadados personalizados sobre o feature flag a eventos de avaliação.

Publicação de telemetria personalizada

O gerenciador de recursos tem sua própria ActivitySource instância chamada Microsoft.FeatureManagement. Se a telemetria estiver habilitada para um sinalizador de recurso:

  • Quando uma avaliação de sinalizador de recurso é iniciada, o gerenciador de recursos inicia uma instância de Activity.
  • Quando uma avaliação de sinalizador de recurso é concluída, o gerenciador de funcionalidades adiciona uma instância ActivityEvent com o nome FeatureFlag à atividade atual.

O evento FeatureFlag tem tags que incluem as informações sobre a avaliação do flag de recurso. As tags usam os campos definidos no esquema FeatureEvaluationEvent.

Observação

Todos os pares chave-valor especificados na telemetry.metadata propriedade do sinalizador de recurso também são incluídos nas tags.

Para habilitar a publicação de telemetria personalizada, você pode criar uma instância ActivityListener e escutar a fonte de atividade Microsoft.FeatureManagement. O código a seguir mostra como ouvir a origem da 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, consulte Coletar um rastreamento distribuído.

Application Insights Telemetry

O pacote Microsoft.FeatureManagement.Telemetry.ApplicationInsights fornece um editor de telemetria interno que envia dados de avaliação do sinalizador de recurso para o Application Insights. O pacote Microsoft.FeatureManagement.Telemetry.ApplicationInsights também fornece um inicializador de telemetria que marca automaticamente todos os eventos com TargetingId para que os eventos sejam vinculados a avaliações de sinalizador. Para aproveitar essa funcionalidade, adicione uma referência ao pacote e registre a telemetria do Application Insights. O código a seguir fornece um exemplo:

builder.services
    .AddFeatureManagement()
    .AddApplicationInsightsTelemetry();

Observação

Para ajudar a garantir que a telemetria do Application Insights funcione conforme o esperado, você deve usar a TargetingHttpContextMiddleware classe.

Para habilitar a persistência do contexto de direcionamento na atividade atual, você pode usar a TargetingHttpContextMiddleware classe.

app.UseMiddleware<TargetingHttpContextMiddleware>();

Para obter um exemplo de seu uso, consulte o exemplo VariantAndTelemetryDemo .

Pré-requisito

O editor de telemetria fornecido pelo pacote requer que o Microsoft.FeatureManagement.Telemetry.ApplicationInsights Application Insights seja configurado e registrado como um serviço de aplicativo. Para obter o código de exemplo, consulte o aplicativo de exemplo VariantAndTelemetryDemo .

Cache

O estado do recurso é fornecido pelo sistema IConfiguration. Espera-se que os provedores de configuração gerenciem qualquer armazenamento em cache e atualização dinâmica. O gerenciador de recursos solicita IConfiguration o valor mais recente do estado de um recurso sempre que ele avalia se um recurso está habilitado.

Instantâneo

Alguns cenários exigem que o estado de um recurso permaneça consistente durante o tempo de vida de uma solicitação. Os valores retornados de uma implementação padrão IVariantFeatureManager podem ser alterados se a origem IConfiguration da qual ele extrai for atualizada durante a solicitação.

Você pode impedir esse comportamento usando IVariantFeatureManagerSnapshot. Você pode recuperar IVariantFeatureManagerSnapshot da mesma maneira que IVariantFeatureManager. IVariantFeatureManagerSnapshot implementa a IVariantFeatureManager interface, mas IVariantFeatureManagerSnapshot armazena em cache o primeiro estado avaliado de um recurso durante uma solicitação. Retorna esse estado durante o tempo de vida da funcionalidade.

Provedores de recursos personalizados

Ao implementar um provedor de recursos personalizado, você pode extrair sinalizadores de recursos de fontes como um banco de dados ou um serviço de gerenciamento de recursos. O provedor de recursos padrão extrai sinalizadores de recursos do sistema de configuração do .NET Core. Esse sistema fornece suporte para definir recursos em um arquivo appsettings.json ou em provedores de configuração, como a Configuração de Aplicativos do Azure. Você pode personalizar esse comportamento para controlar de onde as definições de recurso são lidas.

Para personalizar o carregamento de definições de recurso, você deve implementar a IFeatureDefinitionProvider interface.

public interface IFeatureDefinitionProvider
{
    Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);

    IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}

Para usar uma implementação de IFeatureDefinitionProvider, você deve adicioná-la à coleção de serviços antes de adicionar o gerenciamento de funcionalidades. O exemplo a seguir adiciona uma implementação de IFeatureDefinitionProvider chamada InMemoryFeatureDefinitionProvider.

services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
        .AddFeatureManagement()

Próximas etapas

Para descobrir como usar sinalizadores de recursos em seus aplicativos, confira os seguintes guias de início rápido:

Para descobrir como usar filtros de recursos, confira os seguintes tutoriais: