Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Med JavaScript-funktionshanteringsbiblioteket kan du utveckla och exponera programfunktioner baserat på funktionsflaggor. När en ny funktion har utvecklats har många program särskilda krav, till exempel när funktionen ska aktiveras och under vilka villkor. Det här biblioteket är ett sätt att definiera dessa relationer och integreras även i vanliga JavaScript-kodmönster för att göra det möjligt att exponera dessa funktioner.
Funktionsflaggor är ett sätt för JavaScript-program att aktivera eller inaktivera funktioner dynamiskt. Utvecklare kan använda funktionsflaggor i enkla användningsfall som villkorssatser.
Här är några av fördelarna med att använda JavaScript-funktionshanteringsbiblioteket:
- En vanlig konvention för funktionshantering
- Låg barriär för inträde
- Stöder både JSON-objekt och kartbaserade funktionsflaggakällor
- Stöder användning i både Node.js- och webbläsarmiljöer
- Livslängdshantering för funktionsflaggor med Azure App Configuration
- Konfigurationsvärden kan ändras i realtid
- Enkla till komplexa scenarier som omfattas
- Växla på/av-funktioner via deklarativ konfigurationsfil
- Utvärdera funktionstillstånd dynamiskt baserat på anrop till server
JavaScript-funktionshanteringsbiblioteket är öppen källkod. Mer information finns på GitHub-lagringsplatsen.
Kommentar
Vi rekommenderar att du använder funktionshanteringsbiblioteket tillsammans med Azure App Configuration. Azure App Configuration är en lösning för central hantering av programinställningar och funktionsflaggor. Mer information finns i det här avsnittet.
Funktionsflaggor
Funktionsflaggor består av två delar, ett namn och en lista över funktionsfilter som används för att aktivera funktionen.
Filter för funktioner
Funktionsfilter definierar ett scenario för när en funktion ska aktiveras. När en funktion utvärderas för om den är på eller av bläddras listan över funktionsfilter igenom tills ett av filtren bestämmer att funktionen ska aktiveras. I det här läget anses funktionen vara aktiverad och genomströmning via funktionsfiltren stoppas. Om inget funktionsfilter anger att funktionen ska vara aktiverad anses den vara inaktiverad.
Ett funktionsfilter för Microsoft Edge-webbläsare kan till exempel utformas. Det här funktionsfiltret aktiverar alla funktioner som är kopplade till den, så länge en HTTP-begäran kommer från Microsoft Edge.
Konfiguration av funktionsflagga
I JavaScript använder utvecklare ofta objekt eller mappar som de primära datastrukturerna för att representera konfigurationer. JavaScript-funktionshanteringsbiblioteket stöder båda konfigurationsmetoderna, vilket ger utvecklare flexibilitet att välja det alternativ som bäst passar deras behov.
FeatureManager kan läsa funktionsflaggor från olika typer av konfigurationer med hjälp av de inbyggda ConfigurationObjectFeatureFlagProvider och 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);
Använda funktionsflaggor från Azure App Configuration
I stället för att hårdkoda funktionsflaggor i ditt program rekommenderar vi att du håller funktionsflaggor utanför programmet och hanterar dem separat. På så sätt kan du ändra flaggtillstånd när som helst och låta ändringarna börja gälla i programmet direkt. Azure App Configuration Service tillhandahåller ett dedikerat portalgränssnitt för att hantera alla dina funktionsflaggor. Se handledningen.
Azure App Configuration Service levererar också funktionsflaggor till ditt program direkt via javascript-klientbiblioteket @azure/app-configuration-provider. I följande exempel visas hur du använder biblioteket.
JavaScript-providern för appkonfiguration innehåller funktionsflaggor i ett Map objekt. Den inbyggda ConfigurationMapFeatureFlagProvider funktionen hjälper till att läsa in funktionsflaggor i det här fallet.
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://free.blessedness.top/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);
Använda Azure App Configuration för att dynamiskt styra funktionsflaggans tillstånd
Azure App Configuration är inte bara en lösning för att externalisera lagring och centraliserad hantering av dina funktionsflaggor, utan du kan också aktivera/inaktivera funktionsflaggor dynamiskt.
Om du vill aktivera dynamisk uppdatering för funktionsflaggor måste du konfigurera refresh egenskapen featureFlagOptions för när du läser in funktionsflaggor från 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);
Du måste anropa refresh metoden för att få det senaste funktionsflaggatillståndet.
await appConfig.refresh(); // Refresh to get the latest feature flags
const isBetaEnabled = await featureManager.isEnabled("Beta");
console.log(`Beta is enabled: ${isBetaEnabled}`);
Kommentar
Mer information om hur du använder funktionshanteringsbiblioteket med Azure App Configuration finns i snabbstarten.
Deklaration av funktionsflagga
I följande exempel visas det format som används för att konfigurera funktionsflaggor i en JSON-fil.
{
"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"
}
}
]
}
}
]
}
}
Avsnittet feature_management används enligt konvention för att ladda inställningar för funktionsflagga. Avsnittet feature_flags är en lista över funktionsflaggor som läses in i biblioteket. I avsnittet ovan ser vi tre olika funktioner. Funktioner definierar sina funktionsfilter med egenskapen client_filters inuti conditions. I funktionsfiltren för FeatureT ser vi att enabled är true utan att några filter har definierats, vilket resulterar i att FeatureT alltid returnerar true.
FeatureU är samma som FeatureT men med enabled resulterar false i att funktionen alltid returnerar false.
FeatureV anger ett funktionsfilter med namnet Microsoft.TimeWindow.
FeatureV är ett exempel på ett konfigurerbart funktionsfilter. Vi kan se i exemplet att filtret har en parameters egenskap. Egenskapen parameters används för att konfigurera filtret. I det här fallet konfigureras start- och sluttiderna för funktionen som ska vara aktiv.
Det detaljerade schemat för feature_management avsnittet finns här.
Avancerat: Användning av kolon :är förbjuden i funktionsflaggans namn.
Kravtyp
Egenskapen requirement_type för en funktionsflagga används för att avgöra om filtren ska använda Any eller All logik när du utvärderar tillståndet för en funktion. Om requirement_type inte anges är Anystandardvärdet .
-
Anyinnebär att endast ett filter behöver utvärderas till sant för att funktionen ska aktiveras. -
Allinnebär att varje filter måste utvärderas till sant för att funktionen ska aktiveras.
En requirement_type av All ändrar traderingen. Om det inte finns några filter inaktiveras funktionen. Sedan bläddras funktionsfiltren igenom tills ett av filtren bestämmer att funktionen ska inaktiveras. Om inget filter anger att funktionen ska inaktiveras anses den vara aktiverad.
{
"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"
}
}
]
}
},
]
}
}
I exemplet ovan FeatureW anger en requirement_type av All, vilket innebär att alla dess filter måste utvärderas till true för att funktionen ska aktiveras. I det här fallet är funktionen aktiverad för 50 % av användarna under den angivna tidsperioden.
Förbrukning
Den grundläggande formen av funktionshantering är att kontrollera om en funktionsflagga är aktiverad och sedan utföra åtgärder baserat på resultatet. Kontroll av tillståndet för en funktionsflagga görs via FeatureManagers isEnabled-metod.
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
}
Implementera ett funktionsfilter
Genom att skapa ett funktionsfilter kan du aktivera funktioner baserat på kriterier som du definierar. För att implementera ett funktionsfilter IFeatureFilter måste gränssnittet implementeras.
IFeatureFilter har en name egenskap och en metod med namnet evaluate.
name Bör användas i konfigurationen för att referera till funktionsfiltret i en funktionsflagga. När en funktion anger att den kan aktiveras för ett funktionsfilter evaluate anropas metoden. Om evaluate returnerar trueinnebär det att funktionen ska vara aktiverad.
interface IFeatureFilter {
name: string;
evaluate(context: IFeatureFilterEvaluationContext, appContext?: unknown): boolean | Promise<boolean>;
}
Följande kodfragment visar hur du implementerar ett anpassat funktionsfilter med namnet MyCriteria.
class MyCriteriaFilter {
name = "MyCriteria";
evaluate(context, appContext) {
if (satisfyCriteria()) {
return true;
}
else {
return false;
}
}
}
Du måste registrera det anpassade filtret under customFilters-egenskapen i det FeatureManagerOptions-objekt som skickas till FeatureManager-konstruktorn.
const featureManager = new FeatureManager(ffProvider, {
customFilters: [
new MyCriteriaFilter() // add custom feature filters under FeatureManagerOptions.customFilters
]
});
Parameteriserade funktionsfilter
Vissa funktionsfilter kräver parametrar för att avgöra om en funktion ska vara aktiverad eller inte. Ett webbläsarfunktionsfilter kan till exempel aktivera en funktion för en viss uppsättning webbläsare. Det kan vara önskvärt att Edge- och Chrome-webbläsare aktiverar en funktion, medan Firefox inte gör det. För att göra detta kan ett funktionsfilter utformas för att förvänta sig parametrar. Dessa parametrar skulle anges i funktionskonfigurationen och i koden skulle vara tillgängliga via parametern IFeatureFilterEvaluationContextIFeatureFilter.Evaluate.
interface IFeatureFilterEvaluationContext {
featureName: string;
parameters?: unknown;
}
IFeatureFilterEvaluationContext har en egenskap med namnet parameters. De här parametrarna representerar en råkonfiguration som funktionsfiltret kan använda för att avgöra hur funktionen ska aktiveras eller inte. Om du vill använda webbläsarfunktionsfiltret som exempel igen kan filtret använda parameters för att extrahera en uppsättning tillåtna webbläsare som skulle anges för funktionen och sedan kontrollera om begäran skickas från någon av dessa webbläsare.
Använda programkontext för funktionsutvärdering
Ett funktionsfilter kan behöva programkontext för körning för att utvärdera en funktionsflagga. Du kan skicka kontexten som en parameter när du anropar isEnabled.
featureManager.isEnabled("Beta", { userId : "Sam" })
Funktionsfiltret kan dra nytta av den kontext som skickas när isEnabled anropas. Programkontexten skickas in som den andra parametern i IFeatureFilter.Evaluate.
Inbyggda funktionsfilter
Det finns två funktionsfilter som medföljer FeatureManagement paketet: TimeWindowFilter och TargetingFilter. Alla inbyggda funktionsfilter läggs till som standard när du skapar FeatureManager.
Vart och ett av de inbyggda funktionsfiltren har sina egna parametrar. Här är listan över funktionsfilter tillsammans med exempel.
Microsoft.TimeWindow
Det här filtret ger möjlighet att aktivera en funktion baserat på ett tidsfönster. Om endast End anges betraktas funktionen som aktiverad fram till dess. Om endast Start anges betraktas funktionen som påslagen vid alla tidpunkter efter den tiden.
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
Tidsfönstret kan konfigureras att upprepas regelbundet. Detta kan vara användbart för scenarier där man kan behöva aktivera en funktion under en låg eller hög trafikperiod på en dag eller vissa dagar i veckan. Om du vill expandera det enskilda tidsfönstret till återkommande tidsfönster bör upprepningsregeln anges i parametern Recurrence .
Kommentar
Start och End måste båda anges för att aktivera Recurrence.
"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"
}
}
}
}
]
Recurrence Inställningarna består av två delar: Pattern (hur ofta tidsfönstret upprepas) och Range (hur länge upprepningsmönstret upprepas).
Upprepningsmönster
Det finns två möjliga typer av upprepningsmönster: Daily och Weekly. Ett tidsfönster kan till exempel upprepa "varje dag", "var tredje dag", "varje måndag" eller "varannan fredag".
Beroende på typ, krävs vissa fält av Pattern, är valfria eller ignoreras.
DailyDet dagliga upprepningsmönstret gör att tidsfönstret upprepas baserat på ett antal dagar mellan varje förekomst.
Egendom Relevans beskrivning Type Krävs Måste anges till Daily.Intervall Valfritt Anger antalet dagar mellan varje förekomst. Standardvärdet är 1. WeeklyDet veckovisa upprepningsmönstret gör att tidsfönstret upprepas samma dag eller dagar i veckan, baserat på antalet veckor mellan varje uppsättning förekomster.
Egendom Relevans beskrivning Type Krävs Måste anges till Weekly.DaysOfWeek Krävs Anger vilka dagar i veckan händelsen inträffar. Intervall Valfritt Anger antalet veckor mellan varje uppsättning förekomster. Standardvärdet är 1. FirstDayOfWeek Valfritt Anger vilken dag som anses vara den första dagen i veckan. Standardvärdet är Sunday.I följande exempel upprepas tidsfönstret varannan måndag och tisdag
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Kommentar
Start måste vara en giltig första förekomst som passar upprepningsmönstret. Dessutom kan tidsfönstrets varaktighet inte vara längre än hur ofta det inträffar. Det är till exempel ogiltigt att ett 25-timmars tidsfönster upprepas varje dag.
Upprepningsintervall
Det finns tre möjliga typer av upprepningsintervall: NoEnd, EndDate och Numbered.
NoEndIntervallet
NoEndgör att upprepningen sker på obestämd tid.Egendom Relevans beskrivning Type Krävs Måste anges till NoEnd.EndDateIntervallet
EndDategör att tidsfönstret inträffar på alla dagar som passar det tillämpliga mönstret fram till slutdatumet.Egendom Relevans beskrivning Type Krävs Måste anges till EndDate.Slutdatum Krävs Anger datumtiden för att sluta tillämpa mönstret. Så länge starttiden för den senaste förekomsten infaller före slutdatumet tillåts sluttiden för den händelsen att sträcka sig längre än den. I följande exempel upprepas tidsfönstret varje dag tills den sista förekomsten inträffar den 1 april 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" } }NumberedIntervallet
Numberedgör att tidsfönstret inträffar ett fast antal gånger (baserat på mönstret).Egendom Relevans beskrivning Type Krävs Måste anges till Numbered.AntalFörekomster Krävs Anger antalet förekomster. I följande exempel upprepas tidsfönstret på måndag och tisdag tills det finns tre förekomster, som inträffar den 1 april (mån), 2 april (tis) och 8 april (mån).
"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 } }
Om du vill skapa en upprepningsregel måste du ange både Pattern och Range. Alla mönstertyper kan fungera med valfri intervalltyp.
Avancerad: Tidszonsförskjutningen för Start egenskapen tillämpas på upprepningsinställningarna.
Microsoft.Targeting
Det här filtret ger möjlighet att aktivera en funktion för en målgrupp. En detaljerad förklaring av målinriktning finns i målinriktningsavsnittet nedan. Filterparametrarna innehåller ett Audience objekt som beskriver användare, grupper, exkluderade användare/grupper och en standardprocent av användarbasen som ska ha åtkomst till funktionen. Varje gruppobjekt som visas i Groups avsnittet måste också ange vilken procentandel av gruppens medlemmar som ska ha åtkomst. Om en användare anges i Exclusion avsnittet, antingen direkt eller om användaren finns i en exkluderad grupp, inaktiveras funktionen. Annars, om en användare anges direkt i Users-avsnittet, eller om användaren är i procentandelen som ingår i någon av grupputrullningarna, eller om användaren hamnar i standardprocenten av utrullningen, kommer den användaren att ha funktionen aktiverad.
"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"
]
}
}
}
}
]
Rikta
Inriktning är en strategi för funktionshantering som gör det möjligt för utvecklare att successivt distribuera nya funktioner till sin användarbas. Strategin bygger på konceptet att rikta in sig på en uppsättning användare som kallas målgruppen. En målgrupp består av specifika användare, grupper, exkluderade användare/grupper och en angiven procentandel av hela användarbasen. De grupper som ingår i målgruppen kan delas upp ytterligare i procent av deras totala medlemmar.
Följande steg visar ett exempel på en progressiv distribution för en ny betafunktion:
- Enskilda användare Jeff och Alicia beviljas åtkomst till betaversionen.
- En annan användare, Mark, ber att få anmäla sig och inkluderas.
- Tjugo procent av en grupp som kallas "Ring1"-användare ingår i betaversionen.
- Antalet "Ring1"-användare som ingår i betaversionen ökar till 100 procent.
- Fem procent av användarbasen ingår i betaversionen.
- Distributionsprocenten höjs till 100 procent och funktionen lanseras helt.
Den här strategin för att lansera en funktion är inbyggd i biblioteket via det inkluderade funktionsfiltret Microsoft.Targeting .
Rikta in sig på en användare med målkontext
Målfiltret förlitar sig på en målkontext för att utvärdera om en funktion ska aktiveras. Den här målkontexten innehåller information som vilken användare som för närvarande utvärderas och vilka grupper användaren befinner sig i. Målkontexten måste skickas direkt när isEnabled anropas.
featureManager.isEnabled("Beta", { userId: "Aiden", groups: ["Ring1"] })
Målundantag
När du definierar en målgrupp kan användare och grupper undantas från målgruppen. Undantag är användbara när en funktion distribueras till en grupp användare, men några användare eller grupper måste undantas från distributionen. Exkludering definieras genom att en lista över användare och grupper läggs till i målgruppens Exclusion egenskap.
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0,
"Exclusion": {
"Users": [
"Mark"
]
}
}
I exemplet ovan är funktionen aktiverad för användare med namnet Jeff och Alicia. Det är också aktiverat för användare i gruppen med namnet Ring0. Men om användaren heter Markinaktiveras funktionen, oavsett om de finns i gruppen Ring0 eller inte. Undantag prioriteras framför resten av målfiltret.
Mål i ett webbprogram
Ett exempel på ett webbprogram som använder målfunktionsfiltret är tillgängligt i det här exempelprojektet .
I webbprogram, särskilt de med flera komponenter eller lager, kan det bli besvärligt och repetitivt att skicka målkontexten (userId och groups) till varje funktionsflaggakontroll. Det här scenariot kallas "kontext för omgivande mål", där användaridentitetsinformationen redan är tillgänglig i programkontexten (till exempel i sessionsdata eller autentiseringskontext) men måste vara tillgänglig för utvärderingar av funktionshantering i hela programmet.
ITargetingContextAccessor
Biblioteket tillhandahåller en lösning genom ITargetingContextAccessor mönstret.
interface ITargetingContext {
userId?: string;
groups?: string[];
}
interface ITargetingContextAccessor {
getTargetingContext: () => ITargetingContext | undefined;
}
I stället för att uttryckligen skicka målkontexten med varje isEnabled eller getVariant anrop kan du ange en funktion som vet hur den aktuella användarens målinformation ska hämtas från programmets kontext:
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");
Det här mönstret är särskilt användbart i webbprogram på serversidan där användarkontexten kan vara tillgänglig i ett omfång för begäran eller i klientprogram där användaridentiteten hanteras centralt.
Använda AsyncLocalStorage för begärandekontext
En vanlig utmaning när du implementerar mönstret för kontextåtkomst för mål är att upprätthålla begärandekontexten i en asynkron anropskedja. I Node.js webbprogram är användaridentitetsinformation vanligtvis tillgänglig i begärandeobjektet, men blir otillgänglig när du anger asynkrona åtgärder.
Node.js tillhandahåller AsyncLocalStorage från modulen async_hooks för att lösa det här problemet. Det skapar ett arkiv som bevaras mellan asynkrona åtgärder inom samma logiska "kontext" – perfekt för att underhålla begärandedata under hela begärandelivscykeln.
Så här implementerar du en kontextåtkomst för inriktning med hjälp av AsyncLocalStorage i en express-applikation:
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 = requestAccesor.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 || []
};
}
};
Varianter
När nya funktioner läggs till i ett program kan det hända att en funktion har flera olika föreslagna designalternativ. En vanlig lösning för att bestämma en design är någon form av A/B-testning, vilket innebär att tillhandahålla en annan version av funktionen till olika segment av användarbasen och välja en version baserat på användarinteraktion. I det här biblioteket aktiveras den här funktionen genom att representera olika konfigurationer av en funktion med varianter.
Varianter gör det möjligt för en funktionsflagga att bli mer än en enkel på/av-flagga. En variant representerar ett värde för en funktionsflagga som kan vara en sträng, ett tal, ett booleskt objekt eller till och med ett konfigurationsobjekt. En funktionsflagga som deklarerar varianter bör definiera under vilka omständigheter varje variant ska användas, vilket beskrivs mer detaljerat i avsnittet Allokera varianter .
Hämta en variant med målkontext
För varje funktion kan en variant hämtas med metoden FeatureManager's getVariant . Varianttilldelningen är beroende av den användare som för närvarande utvärderas och den informationen hämtas från målkontexten som du skickade in. Om du har registrerat en målkontextåtkomst till FeatureManagerhämtas målkontexten automatiskt från den. Men du kan fortfarande åsidosätta det genom att manuellt skicka målkontexten när du anropar 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
Deklaration av variantfunktionsflagga
Jämfört med normala funktionsflaggor har variantfunktionsflaggor ytterligare två egenskaper: variants och allocation. Egenskapen variants är en matris som innehåller de varianter som definierats för den här funktionen. Egenskapen allocation definierar hur dessa varianter ska allokeras för funktionen. Precis som när du deklarerar normala funktionsflaggor kan du konfigurera variantfunktionsflaggor i en JSON-fil. Här är ett exempel på en variantfunktionsflagga.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
Definiera varianter
Varje variant har två egenskaper: ett namn och en konfiguration. Namnet används för att referera till en specifik variant och konfigurationen är värdet för den varianten. Konfigurationen kan anges med hjälp av configuration_value egenskapen .
configuration_value är en infogad konfiguration som kan vara ett sträng-, tal-, booleskt eller konfigurationsobjekt. Om configuration_value inte anges är egenskapen configuration hos varianten som returneras undefined.
En lista över alla möjliga varianter definieras för varje funktion under egenskapen variants .
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
Allokera varianter
Processen för att allokera en funktions varianter bestäms av allocation funktionens egenskap.
"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"
}
]
Inställningen allocation för en funktion har följande egenskaper:
| Egendom | beskrivning |
|---|---|
default_when_disabled |
Anger vilken variant som ska användas när en variant begärs medan funktionen anses vara inaktiverad. |
default_when_enabled |
Anger vilken variant som ska användas när en variant begärs medan funktionen anses vara aktiverad och ingen annan variant har tilldelats användaren. |
user |
Anger en variant och en lista över användare som den varianten ska tilldelas till. |
group |
Anger en variant och en lista över grupper. Varianten tilldelas om användaren finns i minst en av grupperna. |
percentile |
Anger en variant och ett procentintervall som användarens beräknade procentandel måste passa in i för att den varianten ska tilldelas. |
seed |
Värdet som procentberäkningar för percentile baseras på. Procentberäkningen för en viss användare blir densamma för alla funktioner om samma seed värde används. Om inget seed anges skapas ett standardutsäde baserat på funktionsnamnet. |
Om funktionen inte är aktiverad tilldelar funktionshanteraren den variant som markerats som default_when_disabled till den aktuella användaren, vilket i det här fallet är Small .
Om funktionen är aktiverad kontrollerar funktionshanteraren allokeringarna user, group, och percentile i den angivna ordningen för att tilldela en variant. I det här exemplet, om användaren som utvärderas heter Marsha, i gruppen med namnet Ring1, eller om användaren råkar falla mellan 0 och 10:e percentilen, tilldelas den angivna varianten till användaren. I det här fallet returnerar alla tilldelade användare varianten Big . Om ingen av dessa allokeringar matchar tilldelas användaren varianten default_when_enabled , som är Small.
Allokeringslogik liknar funktionsfiltret Microsoft.Targeting , men det finns vissa parametrar som finns i mål som inte finns i allokering och vice versa. Resultatet av mål och allokering är inte relaterade.
Åsidosätta aktiverat tillstånd med en variant
Du kan använda varianter för att åsidosätta det aktiverade tillståndet för en funktionsflagga. Överstyrning ger varianter en möjlighet att utöka utvärderingen av en feature-flagga. När du anropar is_enabled en flagga med varianter kontrollerar funktionshanteraren om den variant som tilldelats den aktuella användaren har konfigurerats för att åsidosätta resultatet. Åsidosättande görs med den valfria variantegenskapen status_override. Som standard är den här egenskapen inställd på None, vilket innebär att varianten inte påverkar om flaggan anses vara aktiverad eller inaktiverad. Genom att ställa in status_override till Enabled tillåts det att varianten, när den väljs, åsidosätter en flagga för att aktiveras. Inställningen status_override ger Disabled motsatt funktionalitet och inaktiverar därför flaggan när varianten väljs. En egenskap med ett enabled tillstånd av false kan inte överskridas.
Om du använder en funktionsflagga med binära varianter kan egenskapen status_override vara användbar. Det gör att du kan fortsätta använda API:er som is_enabled i ditt program, samtidigt som du drar nytta av de nya funktionerna som medföljer varianter, till exempel percentilallokering och startvärde.
{
"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"
}
]
}
I exemplet ovan är funktionen alltid aktiverad. Om den aktuella användaren är i det beräknade percentilintervallet på 10 till 20 returneras varianten On . Annars returneras varianten Off och eftersom status_override är lika Disabledmed betraktas funktionen nu som inaktiverad.
Telemetri
När en ändring av funktionsflaggan distribueras är det ofta viktigt att analysera dess effekt på ett program. Här är till exempel några frågor som kan uppstå:
- Är mina flaggor aktiverade/inaktiverade som förväntat?
- Får målanvändare åtkomst till en viss funktion som förväntat?
- Vilken variant ser en viss användare?
Dessa typer av frågor kan besvaras genom emittering och analys av utvärderingshändelser för funktionsflaggor.
Aktivera telemetri
Som standard har funktionsflaggor ingen telemetri genererad. Om du vill publicera telemetri för en viss funktionsflagga måste flaggan deklarera att den är aktiverad för telemetriutsläpp.
För funktionsflaggor som definierats i json görs aktiveringen med hjälp telemetry av egenskapen .
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
Kodfragmentet ovan definierar en funktionsflagga med namnet MyFeatureFlag som är aktiverad för telemetri. Objektets telemetryenabled egenskap är inställd på true. Värdet för egenskapen enabled måste vara true att publicera telemetri för flaggan.
Avsnittet telemetry i en funktionsflagga har följande egenskaper:
| Egendom | beskrivning |
|---|---|
enabled |
Anger om telemetri ska publiceras för funktionsflaggan. |
metadata |
En samling nyckel/värde-par, modellerade som en ordlista, som kan användas för att bifoga anpassade metadata om funktionsflaggan till utvärderingshändelser. |
Anpassad telemetripublicering
Du kan registrera en onFeatureEvaluated återanropsfunktion när du skapar FeatureManager. Det här återanropet anropas när en funktionsflagga utvärderas och telemetri aktiveras för den flaggan. Återanropsfunktionen tar funktionsutvärderingsresultatet som parameter.
I följande exempel visas hur du implementerar en anpassad återanropsfunktion för att skicka telemetri med den information som extraheras från funktionsutvärderingsresultatet och registrerar den till funktionshanteraren.
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});
Application Insights-integrering
JavaScript-funktionshanteringsbiblioteket innehåller tilläggspaket som integreras med Application Insights SDK:er.
Application Insights erbjuder olika SDK:er för webb- och Node.js scenarier. Välj rätt tilläggspaket för ditt program.
Om programmet körs i webbläsaren installerar du "@microsoft/feature-management-applicationinsights-browser" paketet. I följande exempel visas hur du kan skapa en inbyggd Application Insights-telemetriutgivare och registrera den i funktionshanteraren.
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"});
Telemetriutgivaren skickar FeatureEvaluation anpassade händelser till Application Insights när en funktionsflagga aktiverad med telemetri utvärderas. Den anpassade händelsen följer schemat FeatureEvaluationEvent .
Rikta in sig på telemetriprocessor
Om du har implementerat ITargetingContextAccessorkan du använda den inbyggda Application Insights-telemetriprocessorn för att automatiskt koppla mål-ID-information till all telemetri genom att anropa createTargetingTelemetryProcessor funktionen.
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)
);
Detta säkerställer att varje telemetriobjekt som skickas till Application Insights innehåller användarens mål-ID-information (userId och grupper), så att du kan korrelera användning av funktionsflagga med specifika användare eller grupper i din analys.
Om du använder måltelemetriprocessorn kan du anropa metoden direkt trackEvent från Application Insights SDK i stället för att anropa metoden trackEvent som tillhandahålls av funktionshanteringspaketet. Mål-ID-informationen kopplas automatiskt till den anpassade händelsetelemetrins 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" });
Nästa steg
Om du vill lära dig hur du använder funktionsflaggor i dina program fortsätter du till följande snabbstarter.
Fortsätt till följande handledningar om du vill lära dig hur du använder funktionsfilter.