Partager via


Gestion des fonctionnalités JavaScript

feature-management-npm-package

La bibliothèque de gestion des fonctionnalités JavaScript permet de développer et d’exposer les fonctionnalités d’application en fonction des indicateurs de fonctionnalité. Une fois qu’une nouvelle fonctionnalité est développée, de nombreuses applications ont des exigences particulières, par exemple quand la fonctionnalité doit être activée et dans quelles conditions. Cette bibliothèque fournit un moyen de définir ces relations et s’intègre également aux modèles de code JavaScript courants pour rendre possible l’exposition de ces fonctionnalités.

Les indicateurs de fonctionnalité permettent aux applications JavaScript d’activer ou de désactiver dynamiquement des fonctionnalités. Les développeurs peuvent utiliser des indicateurs de fonctionnalité dans des cas d’utilisation simples tels que des instructions conditionnelles.

Voici quelques-uns des avantages de l’utilisation de la bibliothèque de gestion des fonctionnalités JavaScript :

  • Une convention commune pour la gestion des fonctionnalités
  • Prise en main rapide
    • Prend en charge les objets JSON et les sources d’indicateur de fonctionnalité basées sur un mappage
    • Prend en charge l’utilisation dans les environnements Node.js et de navigateur
  • Gestion de la durée de vie des indicateurs de fonctionnalité avec Azure App Configuration
    • Les valeurs de configuration peuvent changer en temps réel
  • Scénarios simples à complexes couverts
    • Activation/désactivation des fonctionnalités via le fichier de configuration déclaratif
    • Évaluation dynamique de l’état de la fonctionnalité en fonction de l’appel au serveur

La bibliothèque de gestion des fonctionnalités JavaScript est open source. Pour plus d’informations, visitez le dépôt GitHub.

Remarque

Il est recommandé d’utiliser la bibliothèque de gestion des fonctionnalités avec Azure App Configuration. Azure App Configuration fournit une solution pour la gestion centralisée des paramètres d’application et des indicateurs de fonctionnalité. Pour plus d’informations, consultez cette section.

Indicateurs de fonctionnalités

Les indicateurs de fonctionnalité sont composés de deux parties : un nom et une liste de filtres de fonctionnalités utilisés pour activer la fonctionnalité.

Filtres de fonctionnalités

Les filtres de fonctionnalités définissent un scénario pour lequel une fonctionnalité doit être activée. Lorsque l’activation ou la désactivation d’une fonctionnalité est évaluée, sa liste de filtres de fonctionnalités est parcourue jusqu’à ce qu’un des filtres décide que la fonctionnalité doit être activée. À ce stade, la fonctionnalité est considérée comme activée et le parcours des filtres de fonctionnalités s’arrête. Si aucun filtre de fonctionnalités n’indique que la fonctionnalité doit être activée, elle est considérée comme désactivée.

Par exemple, un filtre de fonctionnalités de navigateur Microsoft Edge peut être conçu. Ce filtre de fonctionnalité active toutes les fonctionnalités auxquelles il est attaché, à condition qu’une requête HTTP provienne de Microsoft Edge.

Configuration de l’indicateur de fonctionnalité

En JavaScript, les développeurs utilisent couramment des objets ou des mappages comme structures de données principales pour représenter des configurations. La bibliothèque de gestion des fonctionnalités JavaScript prend en charge les deux approches de configuration, ce qui permet aux développeurs de choisir l’option qui convient le mieux à leurs besoins. Le FeatureManager peut lire les indicateurs de fonctionnalité dans différents types de configuration en utilisant les éléments intégrés ConfigurationObjectFeatureFlagProvider et 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);

Utiliser des indicateurs de fonctionnalités d’Azure App Configuration

Plutôt que de coder en dur vos indicateurs de fonctionnalités dans votre application, nous vous recommandons de conserver les indicateurs de fonctionnalités en dehors de l’application et de les gérer séparément. Cela vous permet de modifier l’état des indicateurs à tout moment, et d’appliquer immédiatement ces changements dans l’application. Le service Azure App Configuration fournit une interface utilisateur de portail dédiée pour la gestion de tous les indicateurs de fonctionnalités. Consultez le tutoriel.

Le service Azure App Configuration délivre également les indicateurs de fonctionnalités à votre application directement via ses bibliothèques de client JavaScript @azure/app-configuration-provider. L’exemple suivant montre comment utiliser la bibliothèque.

Le fournisseur JavaScript d’App Configuration les indicateurs de fonctionnalité dans un objet Map. Le ConfigurationMapFeatureFlagProvider intégré permet de charger des indicateurs de fonctionnalité dans ce cas.

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

Utiliser Azure App Configuration pour contrôler dynamiquement l’état de l’indicateur de fonctionnalité

Azure App Configuration n’est pas seulement une solution pour externaliser le stockage et la gestion centralisée de vos indicateurs de fonctionnalité, mais elle permet également d’activer/désactiver dynamiquement les indicateurs de fonctionnalité.

Pour activer l'actualisation dynamique des feature flags, vous devez configurer la propriété refresh lors du chargement des feature flags depuis Azure App Configuration.

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

Vous devez appeler la refresh méthode pour obtenir l’état de l’indicateur de fonctionnalité le plus récent.

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

Remarque

Pour plus d’informations sur l’utilisation de la bibliothèque de gestion des fonctionnalités avec Azure App Configuration, consultez le guide de démarrage rapide.

Déclaration d’indicateur de fonctionnalité

L’exemple suivant montre le format utilisé pour configurer des indicateurs de fonctionnalités dans un fichier 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"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

La section feature_management est utilisée par convention pour charger les paramètres des indicateurs de fonctionnalité. La section feature_flags est une liste des indicateurs de fonctionnalité chargés dans la bibliothèque. Dans la section ci-dessus, nous voyons trois fonctionnalités différentes. Les fonctionnalités définissent leurs filtres de fonctionnalités à l’aide de la propriété client_filters, à l’intérieur de conditions. Dans les filtres de fonctionnalités pour FeatureT, nous voyons que enabled a la valeur true sans aucun filtre défini, ce qui fait que FeatureT retourne toujours true. FeatureU est identique à FeatureT, mais avec enabled défini sur false, ce qui fait que la fonctionnalité retourne toujours false. FeatureV spécifie un filtre de fonctionnalités nommé Microsoft.TimeWindow. FeatureV est un exemple de filtre de fonctionnalité configurable. Nous pouvons voir dans l’exemple que le filtre a une propriété parameters. La propriété parameters est utilisée pour configurer le filtre. Dans ce cas, les heures de début et de fin d’activation de la fonctionnalité sont configurées.

Le schéma détaillé de la section feature_management est disponible ici.

Avancé : l’utilisation du signe deux-points (:) est interdite dans les noms d’indicateurs de fonctionnalité.

Type de condition requise

La propriété requirement_type d’un indicateur de fonctionnalité sert à déterminer si les filtres doivent utiliser la logique Any ou All lors de l’évaluation de l’état d’une fonctionnalité. Si requirement_type n’est pas spécifié, la valeur par défaut est Any.

  • Any signifie qu’un seul filtre doit être évalué sur true pour que la fonctionnalité soit activée.
  • All signifie que tous les filtres doivent être évalués sur true pour que la fonctionnalité soit activée.

Un requirement_type de All modifie le parcours. Tout d’abord, s’il n’existe aucun filtre, la fonctionnalité est désactivée. Ensuite, les filtres de fonctionnalités sont parcourus jusqu’à ce que l’un des filtres décide que la fonctionnalité doit être désactivée. Si aucun filtre n’indique que la fonctionnalité doit être désactivée, elle est considérée comme activée.

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

Dans l’exemple ci-dessus, FeatureW spécifie un requirement_type de All, ce qui signifie que tous ses filtres doivent être évalués sur true pour que la fonctionnalité soit activée. Dans ce cas, la fonctionnalité est activée pour 50 % des utilisateurs pendant la fenêtre de temps spécifiée.

Consommation

La forme de base de la gestion des fonctionnalités consiste à vérifier si un indicateur de fonctionnalité est activé, puis à effectuer des actions en fonction du résultat. Pour vérifier l’état d’un indicateur de fonctionnalité, utilisez la méthode FeatureManager de isEnabled.

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
}

Implémentation d’un filtre de fonctionnalité

La création d’un filtre de fonctionnalités permet d’activer des fonctionnalités en fonction des critères que vous définissez. Pour implémenter un filtre de fonctionnalités, l’interface IFeatureFilter doit être implémentée. IFeatureFilter a une propriété name et une méthode nommée evaluate. La propriété name doit être utilisée dans la configuration pour faire référence au filtre de fonctionnalités dans un indicateur de fonctionnalité. Lorsqu’une fonctionnalité spécifie qu’elle peut être activée pour un filtre de fonctionnalités, la méthode evaluate est appelée. Si evaluate retourne true, cela signifie que la fonctionnalité doit être activée.

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

L’extrait de code suivant montre comment implémenter un filtre de fonctionnalités personnalisé nommé MyCriteria.

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

Vous devez inscrire le filtre personnalisé dans la propriété customFilters de l’objet FeatureManagerOptions passé au constructeur FeatureManager.

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

Filtres de fonctionnalités paramétrables

Certains filtres de fonctionnalités nécessitent des paramètres pour déterminer si une fonctionnalité doit être activée ou non. Par exemple, un filtre de fonctionnalités de navigateur peut activer une fonctionnalité pour un certain ensemble de navigateurs. Il peut être souhaité que les navigateurs Edge et Chrome activent une fonctionnalité, tandis que Firefox ne le fait pas. Pour ce faire, un filtre de fonctionnalités peut être conçu pour attendre des paramètres. Ces paramètres sont spécifiés dans la configuration de la fonctionnalité et sont accessibles dans le code via le paramètre IFeatureFilterEvaluationContext de IFeatureFilter.Evaluate.

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

IFeatureFilterEvaluationContext a une propriété nommée parameters. Ces paramètres représentent une configuration brute que le filtre de fonctionnalités peut utiliser pour déterminer si la fonctionnalité doit être activée ou non. Pour utiliser à nouveau le filtre de fonctionnalités du navigateur comme exemple, le filtre peut utiliser parameters pour extraire un ensemble de navigateurs autorisés qui seraient spécifiés pour la fonctionnalité, puis vérifier si la requête est envoyée à partir de l’un de ces navigateurs.

Utiliser le contexte d’application pour l’évaluation des fonctionnalités

Un filtre de fonctionnalités peut nécessiter un contexte d’application à l’exécution pour évaluer un indicateur de fonctionnalité. Vous pouvez passer le contexte en tant que paramètre lors de l’appel de isEnabled.

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

Le filtre de fonctionnalités peut tirer parti du contexte qui est passé quand isEnabled est appelé. Le contexte d’application est passé en tant que second paramètre de IFeatureFilter.Evaluate.

Filtres de fonctionnalités intégrés

Il existe deux filtres de fonctionnalités fournis avec le FeatureManagement package : TimeWindowFilter et TargetingFilter. Tous les filtres de fonctionnalités intégrés sont ajoutés par défaut lors de la construction de FeatureManager.

Chacun des filtres de fonctionnalités intégrés a ses propres paramètres. Voici la liste des filtres de fonctionnalités, ainsi que des exemples.

Microsoft.TimeWindow

Ce filtre permet d’activer une fonctionnalité en fonction d’une fenêtre de temps. Si uniquement End est spécifié, la fonctionnalité est considérée comme activée jusqu’à cette heure. Si uniquement Start est spécifié, la fonctionnalité est considérée comme activée à tous les points après cette heure.

"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

Ce filtre permet d’activer une fonctionnalité pour un public cible. Une explication détaillée du ciblage est expliquée dans la section sur le ciblage ci-dessous. Les paramètres de filtre incluent un objet Audience qui décrit les utilisateurs, les groupes, les utilisateurs et groupes exclus et un pourcentage par défaut de la base d’utilisateurs qui doit avoir accès à la fonctionnalité. Chaque objet de groupe répertorié dans la section Groups doit également spécifier le pourcentage des membres du groupe qui doivent avoir accès. Si un utilisateur est spécifié dans la section Exclusion, directement ou si l’utilisateur se trouve dans un groupe exclu, la fonctionnalité est désactivée. Sinon, si un utilisateur est spécifié directement dans la section Users, ou si l’utilisateur se trouve dans le pourcentage inclus de l’un des déploiements de groupe, ou si l’utilisateur tombe dans le pourcentage de déploiement par défaut, cette fonctionnalité est activée.

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

Ciblage

Le ciblage est une stratégie de gestion des fonctionnalités qui permet aux développeurs de déployer progressivement de nouvelles fonctionnalités sur leur base d’utilisateurs. La stratégie repose sur le concept de ciblage d’un ensemble d’utilisateurs appelé public cible. Un public est constitué d’utilisateurs, de groupes spécifiques, d’utilisateurs et de groupes exclus, et d’un pourcentage désigné de l’ensemble de la base d’utilisateurs. Les groupes inclus dans le public peuvent être divisés en pourcentages de leurs membres totaux.

Les étapes suivantes illustrent un exemple de déploiement progressif d’une nouvelle fonctionnalité « Bêta » :

  1. Les utilisateurs individuels Jeff et Alicia ont accès à la version bêta.
  2. Un autre utilisateur, Mark, demande à participer et est inclus.
  3. Vingt pour cent d’un groupe appelé utilisateurs « Ring1 » sont inclus dans la version Bêta.
  4. Le nombre d’utilisateurs de « Ring1 » inclus dans la version bêta est passé à 100 %.
  5. 5 % de la base d’utilisateurs sont inclus dans la version bêta.
  6. Le pourcentage de déploiement est passé à 100 % et la fonctionnalité est entièrement déployée.

Cette stratégie de déploiement d’une fonctionnalité est intégrée à la bibliothèque via le filtre de fonctionnalité Microsoft.Targeting inclus.

Ciblage d’un utilisateur avec le contexte de ciblage

Le filtre de ciblage s’appuie sur un contexte de ciblage pour évaluer si une fonctionnalité doit être activée. Ce contexte de ciblage contient des informations telles que l’utilisateur actuellement en cours d’évaluation et les groupes auxquels l’utilisateur appartient. Le contexte de ciblage doit être passé directement quand isEnabled est appelé.

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

Exclusion de ciblage

Lors de la définition d’une audience, vous pouvez exclure des utilisateurs et des groupes de l’audience. Les exclusions sont utiles pour déployer une fonctionnalité sur un groupe d’utilisateurs en excluant quelques utilisateurs ou groupes du déploiement. L’exclusion est définie en ajoutant une liste d’utilisateurs et de groupes à la propriété Exclusion du public.

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

Dans l’exemple ci-dessus, la fonctionnalité est activée pour les utilisateurs nommés Jeff et Alicia. Elle est également activée pour les utilisateurs du groupe nommé Ring0. Toutefois, si l’utilisateur est nommé Mark, la fonctionnalité est désactivée, qu’il se trouve dans le groupe Ring0 ou non. Les exclusions sont prioritaires sur le reste du filtre de ciblage.

Ciblage dans une application web

Un exemple d’application web qui utilise le filtre de fonctionnalités de ciblage est disponible dans cet exemple de projet.

Dans les applications web, en particulier celles avec plusieurs composants ou couches, le passage du contexte de ciblage (userId et groups) à chaque vérification de l’indicateur de fonctionnalité peut devenir fastidieux et répétitif. Ce scénario est appelé « contexte de ciblage ambiant », où les informations d’identité utilisateur sont déjà disponibles dans le contexte de l’application (par exemple, dans les données de session ou le contexte d’authentification), mais doivent être accessibles aux évaluations de gestion des fonctionnalités dans toute l’application.

ITargetingContextAccessor

La bibliothèque fournit une solution par le biais du ITargetingContextAccessor modèle.

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

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

Au lieu de passer explicitement le contexte de ciblage avec chaque isEnabled ou getVariant appel, vous pouvez fournir une fonction qui sait comment récupérer les informations de ciblage de l’utilisateur actuel à partir du contexte de votre application :

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");

Ce modèle est particulièrement utile dans les applications web côté serveur où le contexte utilisateur peut être disponible dans une étendue de requête ou dans les applications clientes où l’identité utilisateur est gérée de manière centralisée.

Utilisation d’AsyncLocalStorage pour le contexte de requête

Un défi courant lors de l'implémentation du modèle d'accesseur de contexte de ciblage est de maintenir le contexte de requête tout au long d'une chaîne d'appels asynchrone. Dans Node.js applications web, les informations d’identité utilisateur sont généralement disponibles dans l’objet de requête, mais devient inaccessible une fois que vous entrez des opérations asynchrones.

Node.js fournit AsyncLocalStorage à partir du async_hooks module pour résoudre ce problème. Il crée un stockage qui persiste au travers des opérations asynchrones dans le même « contexte » logique, permettant de maintenir les données de requête tout au long du cycle de vie de la requête.

Voici comment implémenter un accesseur de contexte de ciblage à l’aide d’AsyncLocalStorage dans une application express :

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

Lorsque de nouvelles fonctionnalités sont ajoutées à une application, il peut arriver qu’une fonctionnalité ait différentes options de conception proposées. Une solution courante pour décider d’une conception est une forme de test A/B, qui implique de fournir une version différente de la fonctionnalité à différents segments de la base d’utilisateurs et de choisir une version en fonction de l’interaction utilisateur. Dans cette bibliothèque, cette fonctionnalité est activée en représentant différentes configurations d’une fonctionnalité avec des variantes.

Les variantes permettent à un indicateur de fonctionnalité de devenir plus qu’un simple indicateur activé/désactivé. Une variante représente une valeur d’un indicateur de fonctionnalité qui peut être une chaîne, un nombre, une valeur booléenne ou même un objet de configuration. Un indicateur de fonctionnalité qui déclare des variantes doit définir dans quelles circonstances chaque variante doit être utilisée, ce qui est abordé plus en détail dans la section Allocation de variantes.

Obtenir une variante avec le contexte de ciblage

Pour chaque fonctionnalité, une variante peut être récupérée dans le FeatureManager à l’aide de sa méthode getVariant. L’affectation de la variante dépend de l’utilisateur actuellement en cours d’évaluation, et ces informations sont obtenues auprès du contexte de ciblage que vous avez passé. Si vous avez enregistré un accesseur de contexte de ciblage sur FeatureManager, le contexte de ciblage sera automatiquement récupéré à partir de celui-ci. Mais vous pouvez toujours le remplacer en passant manuellement le contexte de ciblage lors de l’appel 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

Déclaration d’indicateur de fonctionnalité de variante

Comparés aux indicateurs de fonctionnalité normaux, les indicateurs de fonctionnalité de variante ont deux propriétés supplémentaires : variants et allocation. La propriété variants est un tableau qui contient les variantes définies pour cette fonctionnalité. La propriété allocation définit la façon dont ces variantes doivent être allouées pour la fonctionnalité. Au même titre que la déclaration d’indicateurs de fonctionnalité normaux, vous pouvez configurer des indicateurs de fonctionnalité de variante dans un fichier JSON. Voici un exemple d’indicateur de fonctionnalité de variante.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "enabled": true,
                "allocation": {
                    "default_when_enabled": "Small",
                    "group": [
                        {
                            "variant": "Big",
                            "groups": [
                                "Ring1"
                            ]
                        }
                    ]
                },
                "variants": [
                    { 
                        "name": "Big"
                    },  
                    { 
                        "name": "Small"
                    } 
                ]
            }
        ]
    }
}

Définition de variantes

Chaque variante a deux propriétés : un nom et une configuration. Le nom est utilisé pour faire référence à une variante spécifique, et la configuration est la valeur de cette variante. La configuration peut être définie à l’aide de la propriété configuration_value. configuration_value est une configuration inline qui peut être une chaîne, un nombre, une valeur booléenne ou un objet de configuration. Si vous ne spécifiez pas configuration_value, la propriété configuration de la variante retournée est undefined.

Une liste de toutes les variantes possibles est définie pour chaque fonctionnalité sous la propriété variants.

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

Allocation de variantes

Le processus d’allocation des variantes d’une fonctionnalité est déterminé par la propriété allocation de la fonctionnalité.

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

Le paramètre allocation d’une fonctionnalité a les propriétés suivantes :

Propriété Descriptif
default_when_disabled Spécifie quelle variante doit être utilisée lorsqu’une variante est demandée alors que la fonctionnalité est considérée comme désactivée.
default_when_enabled Spécifie quelle variante doit être utilisée lorsqu’une variante est demandée alors que la fonctionnalité est considérée comme activée et qu’aucune autre variante n’a été affectée à l’utilisateur.
user Spécifie une variante et une liste d’utilisateurs auxquels cette variante doit être affectée.
group Spécifie une variante et une liste de groupes. La variante est affectée si l’utilisateur se trouve dans au moins un des groupes.
percentile Spécifie une variante et une plage de pourcentages dans laquelle le pourcentage calculé de l’utilisateur doit se trouver pour que cette variante soit affectée.
seed La valeur sur laquelle les calculs de pourcentage pour percentile sont basés. Le calcul du pourcentage pour un utilisateur spécifique sera le même pour toutes les fonctionnalités si la même valeur seed est utilisée. Si aucune seed n’est spécifiée, une valeur initiale par défaut est créée en fonction du nom de la fonctionnalité.

Si la fonctionnalité n’est pas activée, le gestionnaire de fonctionnalités affecte la variante marquée comme default_when_disabled à l’utilisateur actuel, qui est Small dans ce cas.

Si la fonctionnalité est activée, le gestionnaire de fonctionnalités vérifie les allocations user, group et percentile dans cet ordre pour affecter une variante. Pour cet exemple particulier, si l’utilisateur évalué est nommé Marsha, dans le groupe nommé Ring1, ou si l’utilisateur se trouve entre le 0 et le 10e centile, la variante spécifiée est affectée à l’utilisateur. Dans ce cas, tous les utilisateurs affectés retournent la variante Big. Si aucune de ces allocations ne correspond, l’utilisateur reçoit la variante default_when_enabled, à savoir Small.

La logique d’allocation est similaire au filtre de fonctionnalités Microsoft.Targeting, mais certains paramètres sont présents dans le ciblage qui ne sont pas dans l’allocation, et inversement. Les résultats du ciblage et de l’allocation ne sont pas liés.

Remplacement de l’état activé par une variante

Vous pouvez utiliser des variantes pour remplacer l’état activé d’un indicateur de fonctionnalité. Le remplacement permet aux variantes d’étendre l’évaluation d’un indicateur de fonctionnalité. Lorsque vous appelez is_enabled sur un indicateur avec des variantes, le gestionnaire de fonctionnalités vérifie si la variante affectée à l’utilisateur actuel est configurée pour remplacer le résultat. Le remplacement est effectué à l’aide de la propriété de variante status_override facultative. Par défaut, cette propriété est définie sur None, ce qui signifie que la variante n’affecte pas si l’indicateur est considéré comme activé ou désactivé. Définir status_override sur Enabled permet à la variante, lorsqu’elle est choisie, de modifier un indicateur sur activé. Définir status_override sur Disabled a le comportement opposé, c’est-à-dire que l’indicateur est désactivé lorsque la variante est choisie. Une fonctionnalité avec un état enabled de false ne peut pas être remplacée.

Si vous utilisez un indicateur de fonctionnalité avec des variantes binaires, la propriété status_override peut être utile. Elle vous permet de continuer à utiliser des API telles que is_enabled dans votre application, tout en bénéficiant des nouvelles fonctionnalités fournies avec des variantes, notamment l’allocation de centile et les valeurs initiales.

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

Dans l’exemple ci-dessus, la fonctionnalité est toujours activée. Si l’utilisateur actuel se trouve dans la plage de centile calculée de 10 à 20, la variante On est retournée. Sinon, la variante Off est retournée et, car status_override est égal à Disabled, et la fonctionnalité sera désormais considérée comme désactivée.

Télémétrie

Lorsqu’un changement d’indicateur de fonctionnalité est déployé, il est souvent important d’analyser son effet sur une application. Par exemple, voici quelques questions qui peuvent survenir :

  • Mes indicateurs sont-ils activés/désactivés comme prévu ?
  • Les utilisateurs ciblés ont-ils accès à une certaine fonctionnalité comme prévu ?
  • Quelle variante un utilisateur particulier voit-il ?

Il est possible de répondre à ces types de questions par le biais de l’émission et de l’analyse des événements d’évaluation des indicateurs de fonctionnalité.

Activation de la télémétrie

Par défaut, les indicateurs de fonctionnalité n’émettent pas de données de télémétrie. Pour publier la télémétrie pour un indicateur de fonctionnalité donné, l’indicateur DOIT déclarer qu’il est activé pour l’émission de la télémétrie.

Pour les indicateurs de fonctionnalité définis en JSON, l’activation se fait à l’aide de la propriété telemetry.

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

L’extrait de code ci-dessus définit un indicateur de fonctionnalité nommé MyFeatureFlag qui est activé pour la télémétrie. La propriété telemetry de l’objet enabled est définie sur true. La valeur de la propriété enabled doit être true pour publier des données de télémétrie pour l’indicateur.

La section telemetry d’un indicateur de fonctionnalité a les propriétés suivantes :

Propriété Descriptif
enabled Spécifie si les données de télémétrie doivent être publiées pour l’indicateur de fonctionnalité.
metadata Une collection de paires clé-valeur, modélisées en tant que dictionnaire, qui peuvent être utilisées pour attacher des métadonnées personnalisées sur l’indicateur de fonctionnalité aux événements d’évaluation.

Publication de la télémétrie personnalisée

Vous pouvez inscrire une fonction de rappel onFeatureEvaluated lors de la création de FeatureManager. Ce rappel est appelé chaque fois qu’un indicateur de fonctionnalité est évalué et que la télémétrie est activée pour cet indicateur. La fonction de rappel va prendre le résultat de l’évaluation des fonctionnalités en tant que paramètre.

L’exemple suivant montre comment implémenter une fonction de rappel personnalisée pour envoyer des données de télémétrie avec les informations extraites du résultat de l’évaluation des fonctionnalités et l’inscrire auprès du gestionnaire de fonctionnalités.

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

Intégration d’Application Insights

La bibliothèque de gestion des fonctionnalités JavaScript fournit des packages d’extension qui s’intègrent aux Kits de développement logiciel (SDK) Application Insights.

Application Insights offre différents Kits de développement logiciel (SDK) pour des scénarios web et Node.js. Sélectionnez les packages d’extension appropriés pour votre application.

Si votre application s’exécute dans le navigateur, installez le package "@microsoft/feature-management-applicationinsights-browser". L’exemple suivant montre comment vous pouvez créer un éditeur de télémétrie Application Insights intégré et l’inscrire auprès du gestionnaire de fonctionnalités.

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

L’éditeur de télémétrie envoie des événements personnalisés FeatureEvaluation à Application Insights quand un indicateur de fonctionnalité activé avec la télémétrie est évalué. L’événement personnalisé suit le schéma FeatureEvaluationEvent.

Ciblage du processeur de télémétrie

Si vous avez implémenté ITargetingContextAccessor, vous pouvez utiliser le processeur de télémétrie Application Insights intégré pour attacher automatiquement des informations d’ID de ciblage à toutes les données de télémétrie en appelant la createTargetingTelemetryProcessor fonction.

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

Cela garantit que chaque élément de télémétrie envoyé à Application Insights inclut les informations d’ID de ciblage de l’utilisateur (userId et groupes), ce qui vous permet de mettre en corrélation l’utilisation de l’indicateur de fonctionnalité avec des utilisateurs ou des groupes spécifiques dans votre analytique.

Si vous utilisez le processeur de télémétrie de ciblage, au lieu d’appeler la trackEvent méthode fournie par le package de gestion des fonctionnalités, vous pouvez appeler directement la trackEvent méthode à partir du Kit de développement logiciel (SDK) Application Insights. Les informations relatives à l’ID de ciblage seront automatiquement jointes au customDimensions de la télémétrie de l’événement personnalisé.

// 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" });

Étapes suivantes

Pour découvrir comment utiliser des indicateurs de fonctionnalité dans vos applications, passez aux guides de démarrage rapide suivants.

Pour découvrir comment utiliser des filtres de fonctionnalités, passez aux tutoriels suivants.