Partilhar via


Gerenciamento de recursos JavaScript

feature-management-npm-pacote

A biblioteca de gerenciamento de recursos JavaScript 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 JavaScript comuns para tornar possível a exposição desses recursos.

Os sinalizadores de recursos fornecem uma maneira para os aplicativos JavaScript ativarem ou desativarem recursos dinamicamente. Os desenvolvedores podem usar sinalizadores de recursos em casos de uso simples, como instruções condicionais.

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

  • Uma convenção comum para o gerenciamento de recursos
  • Baixa barreira à entrada
    • Suporta objetos JSON e fontes de sinalizadores de recursos baseados em mapa
    • Suporta o uso em ambientes Node.js e navegador
  • Gestão do ciclo de vida dos feature flags com o Azure App Configuration
    • Os valores de configuração podem mudar em tempo real
  • Cobertura de cenários desde os mais simples até os mais complexos
    • 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

A biblioteca de gerenciamento de recursos JavaScript é de código aberto. Para obter mais informações, visite o repositório GitHub.

Nota

É recomendável usar a biblioteca de gerenciamento de recursos junto com a Configuração do Aplicativo do Azure. A Configuração de Aplicativo do Azure fornece uma solução para gerenciar centralmente as configurações do aplicativo e os sinalizadores de recursos. Para mais detalhes, consulte esta secção.

Marcas de funcionalidades

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 funcionalidades

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, a funcionalidade é considerada ativada e a passagem pelos filtros da funcionalidade é interrompida. 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 anexados a ele, desde que uma solicitação HTTP seja proveniente do Microsoft Edge.

Configuração do sinalizador de funcionalidade

Em JavaScript, os desenvolvedores geralmente usam objetos ou mapas como as estruturas de dados primárias para representar configurações. A biblioteca de gerenciamento de recursos JavaScript suporta ambas as abordagens de configuração, fornecendo aos desenvolvedores a flexibilidade de escolher a opção que melhor atende às suas necessidades. O FeatureManager pode ler sinalizadores de funcionalidades de diferentes tipos de configuração usando o incorporado ConfigurationObjectFeatureFlagProvider e ConfigurationMapFeatureFlagProvider.

const config = new Map([
    ["feature_management", {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": true
            },
            {
                "id": "FeatureU",
                "enabled": false
            }
        ]
    }],
    ["some other configuration", " some value"]
]);

import { ConfigurationMapFeatureFlagProvider, FeatureManager } from "@microsoft/feature-management";
const featureProvider = new ConfigurationMapFeatureFlagProvider(config);
const featureManager = new FeatureManager(featureProvider);

Usar sinalizadores de recursos da Configuração do Aplicativo do Azure

Em vez de codificar os sinalizadores de recursos em seu aplicativo, recomendamos que você mantenha os sinalizadores de recursos fora do aplicativo e os gerencie separadamente. Isso permite que você modifique os estados de bandeira a qualquer momento e que essas alterações entrem em vigor no aplicativo imediatamente. O serviço de Configuração de Aplicativo do Azure fornece uma interface do usuário de portal dedicada para gerenciar todos os seus sinalizadores de recursos. Veja o tutorial.

O serviço de Configuração de Aplicações do Azure também fornece as flags de funcionalidade para a sua aplicação através da sua biblioteca cliente JavaScript @azure/app-configuration-provider diretamente. O exemplo a seguir mostra como usar a biblioteca.

O provedor JavaScript de Configuração do Aplicativo fornece sinalizadores de recursos em um Map objeto. O elemento incorporado ConfigurationMapFeatureFlagProvider ajuda a carregar os flags de funcionalidades neste caso.

import { DefaultAzureCredential } from "@azure/identity";
import { load } from "@azure/app-configuration-provider";
import { ConfigurationMapFeatureFlagProvider, FeatureManager } from "@microsoft/feature-management";
const appConfig = await load("YOUR_APP-CONFIG-ENDPOINT",
                             new DefaultAzureCredential(), // For more information: https://learn.microsoft.com/javascript/api/overview/azure/identity-readme
                             { featureFlagOptions: { enabled: true } }); // load feature flags from Azure App Configuration service
const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig);
const featureManager = new FeatureManager(featureProvider);

Usar a Configuração do Aplicativo do Azure para controlar dinamicamente o estado do sinalizador de recurso

A Configuração de Aplicativo do Azure não é apenas uma solução para externalizar o armazenamento e o gerenciamento centralizado de seus sinalizadores de recursos, mas também permite ativar/desativar dinamicamente os sinalizadores de recursos.

Para habilitar a atualização dinâmica dos sinalizadores de recurso, deve configurar a propriedade refresh ao carregar os sinalizadores de recurso da Configuração de Aplicativos do Azure featureFlagOptions.

const appConfig = await load("YOUR_APP-CONFIG-ENDPOINT",  new DefaultAzureCredential(),  { 
    featureFlagOptions: { 
        enabled: true,
        refresh: {
            enabled: true, // enable the dynamic refresh for feature flags
            refreshIntervalInMs: 30_000
        }
    } 
});

const featureProvider = new ConfigurationMapFeatureFlagProvider(appConfig);
const featureManager = new FeatureManager(featureProvider);

Você precisa chamar o refresh método para obter o estado de bandeira de recurso mais recente.

await appConfig.refresh(); // Refresh to get the latest feature flags
const isBetaEnabled = await featureManager.isEnabled("Beta");
console.log(`Beta is enabled: ${isBetaEnabled}`);

Nota

Para obter mais informações sobre como usar a biblioteca de gerenciamento de recursos com a Configuração de Aplicativo do Azure, vá para o início rápido.

Declaração de sinalizador de recurso

O exemplo a seguir mostra o formato usado para configurar sinalizadores de recursos em um arquivo JSON.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": true
            },
            {
                "id": "FeatureU",
                "enabled": false
            },
            {
                "id": "FeatureV",
                "enabled": true,
                "conditions": {
                    "client_filters": [
                        {
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

A feature_management seção é usada por convenção para carregar as definições de bandeiras de funcionalidades. A feature_flags seção é uma lista dos sinalizadores de recursos que são carregados na biblioteca. Na seção acima, vemos três características diferentes. As funcionalidades definem os seus filtros de funcionalidades usando a client_filters propriedade, dentro do conditions. Nos filtros de recurso para FeatureT, vemos enabled que está true sem filtros definidos, resultando em FeatureT sempre retornar true . FeatureU é o mesmo que FeatureT mas com enabled está false resultando no recurso sempre retornando false. FeatureV Especifica um filtro de recurso chamado Microsoft.TimeWindow. FeatureV é um exemplo de um filtro de recurso configurável. Podemos ver no exemplo que o filtro tem uma parameters propriedade. A parameters propriedade é usada 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 feature_management seção pode ser encontrado aqui.

Avançado: O uso de dois pontos ':' é proibido em nomes de flags de funcionalidades.

Tipo de requisito

A requirement_type 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 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 altera o percorrido. Primeiro, se não houver filtros, o recurso será desativado. Em seguida, percorrem-se os filtros do recurso até que um deles determine que o recurso deva ser desativado. Se nenhum filtro indicar que o recurso deve ser desativado, ele será considerado habilitado.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureW",
                "enabled": true,
                "conditions": {
                    "requirement_type": "All",
                    "client_filters": [
                        {
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                            }
                        },
                        {
                            "name": "Percentage",
                            "parameters": {
                                "Value": "50"
                            }
                        }
                    ]
                }
            },
        ]
    }
}

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 é habilitado para 50% dos usuários durante a janela de tempo especificada.

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. A verificação do estado de um sinalizador de recurso é feita através FeatureManagerdo isEnabled método .

import { ConfigurationMapFeatureFlagProvider, FeatureManager } from "@microsoft/feature-management";
const featureProvider = new ConfigurationMapFeatureFlagProvider(config);
const featureManager = new FeatureManager(featureProvider);

const isBetaEnabled = await featureManager.isEnabled("Beta");
if (isBetaEnabled) {
    // Do something
}

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 uma name propriedade e um método chamado evaluate. O name deve ser usado na configuração para fazer referência ao filtro de funcionalidade dentro de um sinalizador de funcionalidade. Quando uma funcionalidade especifica que pode ser ativada para um filtro de funcionalidades, o método evaluate é chamado. Se evaluate retornar true, significa que o recurso deve ser habilitado.

interface IFeatureFilter {
    name: string;
    evaluate(context: IFeatureFilterEvaluationContext, appContext?: unknown): boolean | Promise<boolean>;
}

O trecho a seguir demonstra como implementar um filtro de recurso personalizado com o nome MyCriteria.

    class MyCriteriaFilter {
        name = "MyCriteria";
        evaluate(context, appContext) {
            if (satisfyCriteria()) {
                return true;
            }
            else {
                return false;
            }
        }
    }

Você precisa registrar o filtro personalizado sob a customFilters propriedade do FeatureManagerOptions objeto passado para o FeatureManager construtor.

const featureManager = new FeatureManager(ffProvider, {
    customFilters: [
        new MyCriteriaFilter() // add custom feature filters under FeatureManagerOptions.customFilters
    ]
});

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 funcionalidades pode ser concebido para aceitar parâmetros. Esses parâmetros seriam especificados na configuração do recurso, e no código seriam acessíveis através do parâmetro IFeatureFilterEvaluationContext de IFeatureFilter.Evaluate.

interface IFeatureFilterEvaluationContext {
    featureName: string;
    parameters?: unknown;
}

IFeatureFilterEvaluationContext 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.

Usar o contexto da aplicação para avaliação de funcionalidades

Um filtro de funcionalidades pode precisar do contexto de execução para avaliar um flag de funcionalidade. Você pode passar o contexto como um parâmetro ao chamar isEnabled.

featureManager.isEnabled("Beta", { userId : "Sam" })

O filtro de funcionalidades pode aproveitar o contexto que é passado quando isEnabled é chamado. O contexto do aplicativo será passado como o segundo parâmetro do IFeatureFilter.Evaluate.

Filtros de funcionalidades integradas

Há dois filtros de recursos que acompanham o FeatureManagement pacote: TimeWindowFilter e TargetingFilter. Todos os filtros de funcionalidades integradas serão adicionados automaticamente ao construir o FeatureManager.

Cada um dos filtros de funcionalidades incorporadas tem os seus próprios parâmetros. Aqui está a lista de filtros de funcionalidades, juntamente com exemplos.

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.

"client_filters": [
    {
        "name": "Microsoft.TimeWindow",
        "parameters": {
            "Start": "Wed, 01 May 2019 13:59:59 GMT",
            "End": "Mon, 01 Jul 2019 00:00:00 GMT"
        }
    }
]     

Microsoft.Targeting

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 utilizador for especificado na secção Users diretamente, ou se o utilizador estiver na percentagem incluída de qualquer uma das rollouts de grupo, ou se o utilizador se enquadrar na percentagem de rollout padrão, então esse utilizador terá a funcionalidade ativada.

"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"
                    ]
                }
            }
        }
    }
]

Segmentação

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':

  1. Os usuários individuais Jeff e Alicia têm acesso ao Beta.
  2. Outro utilizador, Mark, pede para aderir e é incluído.
  3. Vinte por cento dos usuários de um grupo conhecido como "Ring1" estão incluídos na versão Beta.
  4. O número de usuários "Ring1" incluídos no Beta é aumentado para 100%.
  5. Cinco por cento da base de utilizadores está incluída na versão Beta.
  6. 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.

Segmentar um usuário com contexto de segmentação

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 quais grupos o usuário está. O contexto de segmentação deve ser passado diretamente quando isEnabled é chamado.

featureManager.isEnabled("Beta", { userId: "Aiden", groups: ["Ring1"] })

Segmentação da exclusão

Ao definir uma audiência, os usuários e grupos podem ser excluídos da audiência. As exclusões são úteis para quando um recurso está sendo implementado para um grupo de usuários, mas alguns usuários ou grupos precisam ser excluídos da implantação. A exclusão é definida pela adição de uma lista de utilizadores e grupos à Exclusion propriedade de 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.

Segmentação em um aplicativo Web

Um exemplo de aplicação web que utiliza o filtro de funcionalidade de direcionamento está disponível neste projeto example.

Em aplicativos Web, especialmente aqueles com vários componentes ou camadas, passar o contexto de segmentação (userId e groups) para cada verificação de sinalizador de recurso pode se tornar complicado e repetitivo. Esse cenário é conhecido como "contexto de segmentação ambiental", onde as informações de identidade do usuário já estão disponíveis no contexto do aplicativo (como dados de sessão ou contexto de autenticação), mas precisam estar acessíveis para avaliações de gerenciamento de recursos em todo o aplicativo.

ITargetingContextAccessor

A biblioteca fornece uma solução através do ITargetingContextAccessor padrão.

interface ITargetingContext {
    userId?: string;
    groups?: string[];
}

interface ITargetingContextAccessor {
    getTargetingContext: () => ITargetingContext | undefined;
}

Em vez de passar explicitamente o contexto de segmentação a cada chamada de isEnabled ou getVariant, pode oferecer uma função que saiba como recuperar as informações de segmentação do utilizador atual a partir do contexto da sua aplicação.

import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microsoft/feature-management";

// Create a targeting context accessor that uses your application's auth system
const targetingContextAccessor = {
    getTargetingContext: () => {
        // In a web application, this might access request context or session data
        // This is just an example - implement based on your application's architecture
        return {
            userId: getCurrentUserId(), // Your function to get current user
            groups: getUserGroups()     // Your function to get user groups
        };
    }
};

// Configure the feature manager with the accessor
const featureManager = new FeatureManager(featureProvider, {
    targetingContextAccessor: targetingContextAccessor
});

// Now you can call isEnabled without explicitly providing targeting context
// The feature manager will use the accessor to get the current user context
const isBetaEnabled = await featureManager.isEnabled("Beta");

Esse padrão é particularmente útil em aplicativos Web do lado do servidor onde o contexto do usuário pode estar disponível em um escopo de solicitação ou em aplicativos cliente onde a identidade do usuário é gerenciada centralmente.

Usando AsyncLocalStorage para contexto de solicitação

Um desafio comum ao implementar o padrão de acessador de contexto de destino é manter o contexto de solicitação em toda uma cadeia de chamadas assíncrona. Em aplicativos Web Node.js, as informações de identidade do usuário normalmente estão disponíveis no objeto de solicitação, mas ficam inacessíveis quando você insere operações assíncronas.

Node.js fornece AsyncLocalStorage do módulo async_hooks para resolver este problema. Ele cria um armazenamento que persiste em operações assíncronas dentro do mesmo "contexto" lógico - perfeito para manter os dados da solicitação durante todo o ciclo de vida da solicitação.

Veja como implementar um acessador de contexto de segmentação usando AsyncLocalStorage em um aplicativo expresso:

import { AsyncLocalStorage } from "async_hooks";
import express from "express";

const requestAccessor = new AsyncLocalStorage();

const app = express();
// Middleware to store request context
app.use((req, res, next) => {
    // Store the request in AsyncLocalStorage for this request chain
    requestAccessor.run(req, () => {
        next();
    });
});

// Create targeting context accessor that retrieves user data from the current request
const targetingContextAccessor = {
    getTargetingContext: () => {
        // Get the current request from AsyncLocalStorage
        const request = requestContext.getStore();
        if (!request) {
            return undefined; // Return undefined if there's no current request
        }
        // Extract user data from request (from session, auth token, etc.)
        return {
            userId: request.user?.id,
            groups: request.user?.groups || []
        };
    }
};

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.

Obter uma variante com contexto de segmentação

Para cada funcionalidade, uma variante pode ser recuperada usando o FeatureManager método do getVariant. A atribuição de variante depende do utilizador que está a ser avaliado no momento, e essa informação é obtida a partir do contexto de segmentação que forneceu. Se registaste um acessador de contexto de alvo para o FeatureManager, o contexto de alvo será recuperado automaticamente dele. Mas ainda podes substituí-lo passando manualmente o contexto de direcionamento ao chamar getVariant.

const variant = await featureManager.getVariant("MyVariantFeatureFlag", { userId: "Sam" });

const variantName = variant.name;
const variantConfiguration = variant.configuration;

// Do something with the resulting variant and its configuration

Declaração de sinalizador de funcionalidade variante

Em comparação com os sinalizadores de recursos normais, os sinalizadores de recursos variantes têm mais duas propriedades: 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 flag de funcionalidade 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á undefined.

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

Atribuição de variantes

O processo de alocação das variantes de um recurso é determinado pela allocation propriedade do recurso.

"allocation": { 
    "default_when_disabled": "Small",  
    "default_when_enabled": "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:

Propriedade Descrição
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 é 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 no qual se baseiam os cálculos percentuais para percentile. 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 for especificado seed, uma semente padrão será criada com base no nome da funcionalidade.

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 ativado, o gestor de recursos verificará as alocações user, group e percentile nessa ordem para atribuir uma variante. 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. Nesse caso, todos os usuários atribuídos retornariam 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 funcionalidades Microsoft.Targeting, mas existem alguns parâmetros que estão presentes na segmentação, mas não na alocação, e vice-versa. Os resultados da segmentação e da alocação não estão relacionados.

Substituindo o estado habilitado por uma variante

Você pode usar variantes para substituir o estado ativado de um sinalizador de recurso. A sobreposição dá às variantes a oportunidade de estender a avaliação de um flag de funcionalidades. Ao chamar is_enabled um sinalizador com variantes, o gerenciador de recursos verificará se a variante atribuída ao usuário atual está configurada para substituir o resultado. A substituição é feita usando a propriedade opcional status_override variant. Por padrão, essa propriedade é definida como None, o que significa que a variante não afeta se o sinalizador é considerado habilitado ou desabilitado. Ao configurar status_override para Enabled, a variante, quando escolhida, pode sobrepor um sinalizador para ser ativado. Configurar status_override para Disabled fornece a funcionalidade oposta, o que desativa o sinalizador quando a variante é escolhida. Um recurso com um estado de enabled 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 útil. Permite-lhe continuar a usar APIs como is_enabled na sua aplicação, beneficiando-se ao mesmo tempo das novas funcionalidades que acompanham as variantes, como a alocação de percentis 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.

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.

Habilitando a telemetria

Por padrão, os sinalizadores de recursos não têm telemetria emitida. Para publicar a telemetria de uma determinada funcionalidade, o indicador DEVE declarar que está ativado para envio de telemetria.

Para sinalizadores de recursos definidos em json, a habilitação é feita usando a telemetry propriedade.

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

O trecho acima define um sinalizador de recurso chamado MyFeatureFlag que está habilitado para telemetria. A telemetry propriedade do enabled objeto é definida como true. O valor da enabled propriedade deve ser true para publicar telemetria para o sinalizador.

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

Propriedade Descrição
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 utilizada para adicionar metadados personalizados sobre o sinalizador de recurso a eventos de avaliação.

Publicação de telemetria personalizada

Você pode registrar uma função de retorno de onFeatureEvaluated chamada ao criar FeatureManagero . Este callback é chamado sempre que um feature flag é avaliado e a telemetria é ativada para esse flag. A função de retorno de chamada tomará o resultado da avaliação do recurso como parâmetro.

O exemplo a seguir mostra como implementar uma função de retorno de chamada personalizada para enviar telemetria com as informações extraídas do resultado da avaliação do recurso e registrá-lo no gerenciador de recursos.

const sendTelemetry = (evaluationResult) => {
    const featureId = evaluationResult.feature.id;
    const featureEnabled = evaluationResult.enabled;
    const targetingId = evaluationResult.targetingId;
    const variantName = evaluationResult.variant?.name;
    const variantAssignmentReason = evaluationResult.variantAssignmentReason;
    // custom code to send the telemetry
    // ...
}
const featureManager = new FeatureManager(featureProvider, { onFeatureEvaluated :  sendTelemtry});

Integração do Application Insights

A biblioteca de gerenciamento de recursos JavaScript fornece pacotes de extensão que se integram aos SDKs do Application Insights .

O Application Insights oferece diferentes SDKs para cenários da Web e Node.js . Selecione os pacotes de extensão corretos para o seu aplicativo.

Se a sua aplicação for executada no navegador, instale o pacote "@microsoft/feature-management-applicationinsights-browser". O exemplo a seguir mostra como você pode criar um editor de telemetria interno do Application Insights e registrá-lo no gerenciador de recursos.

import { ApplicationInsights } from "@microsoft/applicationinsights-web"
import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "@microsoft/feature-management";
import { createTelemetryPublisher, trackEvent } from "@microsoft/feature-management-applicationinsights-browser";

const appInsights = new ApplicationInsights({ config: {
    connectionString: "<APPINSIGHTS_CONNECTION_STRING>"
}});
appInsights.loadAppInsights();

const publishTelemetry = createTelemetryPublisher(appInsights);
const provider = new ConfigurationObjectFeatureFlagProvider(jsonObject);
const featureManager = new FeatureManager(provider, {onFeatureEvaluated: publishTelemetry});

// FeatureEvaluation event will be emitted when a feature flag is evaluated
featureManager.getVariant("TestFeature", {userId : TARGETING_ID}).then((variant) => { /* do something*/ });

// Emit a custom event with targeting id attached.
trackEvent(appInsights, TARGETING_ID, {name: "TestEvent"}, {"Tag": "Some Value"});

O publicador de telemetria envia FeatureEvaluation eventos personalizados para o Application Insights quando um sinalizador de recurso com telemetria habilitada é avaliado. O evento personalizado segue o esquema FeatureEvaluationEvent .

Direcionando o processador de telemetria

Se tiver implementado ITargetingContextAccessor, pode usar o processador de telemetria interno do Application Insights para anexar automaticamente as informações de ID de direcionamento a toda a telemetria chamando a função createTargetingTelemetryProcessor.

const appInsights = require("applicationinsights");
appInsights.setup(process.env.APPINSIGHTS_CONNECTION_STRING).start();

const { createTargetingTelemetryProcessor } = require("@microsoft/feature-management-applicationinsights-node");
appInsights.defaultClient.addTelemetryProcessor(
    createTargetingTelemetryProcessor(targetingContextAccessor)
);

Isso garante que cada item de telemetria enviado ao Application Insights inclua as informações de ID de segmentação do utilizador (userId e grupos), permitindo que você correlacione o uso dos flags de funcionalidades com utilizadores ou grupos específicos nas suas análises.

Se você estiver usando o processador de telemetria de destino, em vez de chamar o trackEvent método fornecido pelo pacote de gerenciamento de recursos, poderá chamar diretamente o trackEvent método do SDK do Application Insights. As informações de ID de segmentação serão automaticamente anexadas à telemetria de evento personalizada.customDimensions

// Instead of calling trackEvent and passing the app insights client
// trackEvent(appInsights.defaultClient, "<TARGETING_ID>", {name: "TestEvent",  properties: {"Tag": "Some Value"}});

// directly call trackEvent method provided by App Insights SDK
appInsights.defaultClient.trackEvent({ name: "TestEvent" });

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 funcionalidades, continue para os tutoriais a seguir.