Sdílet prostřednictvím


Správa funkcí JavaScriptu

balíček správy funkcí npm

Knihovna pro správu funkcí JavaScriptu poskytuje způsob, jak vyvíjet a zveřejňovat funkce aplikace na základě příznaků funkcí. Po vytvoření nové funkce má mnoho aplikací zvláštní požadavky, například kdy by měla být tato funkce povolená a za jakých podmínek. Tato knihovna poskytuje způsob, jak tyto relace definovat, a také se integruje do běžných vzorů kódu JavaScriptu, aby bylo možné tyto funkce zpřístupnit.

Příznaky funkcí poskytují pro javascriptové aplikace způsob dynamického zapnutí nebo vypnutí funkcí. Vývojáři můžou používat příznaky funkcí v jednoduchých případech použití, jako jsou podmíněné příkazy.

Tady jsou některé výhody používání knihovny pro správu funkcí JavaScriptu:

  • Běžná konvence správy funkcí
  • Nízká bariéra pro vstup
    • Podporuje jak objekty JSON, tak zdroje příznaků funkcí založené na mapě.
    • Podporuje využití v prostředích Node.js i v prohlížeči.
  • Správa životnosti příznaků funkcí pomocí konfigurace Aplikace Azure
    • Hodnoty konfigurace se můžou v reálném čase měnit.
  • Probírané scénáře jednoduché až složité
    • Zapnutí/vypnutí funkcí prostřednictvím deklarativního konfiguračního souboru
    • Dynamické vyhodnocení stavu funkce na základě volání serveru

Knihovna pro správu funkcí JavaScriptu je opensourcová. Další informace najdete v úložišti GitHub.

Poznámka:

Doporučuje se používat knihovnu pro správu funkcí společně s konfigurací Aplikace Azure. Aplikace Azure Configuration poskytuje řešení pro centrální správu nastavení aplikace a příznaků funkcí. Další podrobnosti najdete v této části.

Hlavní příznaky

Příznaky funkcí se skládají ze dvou částí, názvu a seznamu filtrů funkcí, které se používají k zapnutí funkce.

Filtry funkcí

Filtry funkcí definují scénář, kdy má být funkce povolená. Když se funkce vyhodnotí, jestli je zapnutá nebo vypnutá, její seznam filtrů funkcí se projde, dokud se některý z filtrů nerozhodne, že by měla být funkce povolená. V tomto okamžiku se funkce považuje za povolenou a procházení přes filtry funkcí se zastaví. Pokud žádný filtr funkcí indikuje, že by měla být tato funkce povolená, považuje se za zakázanou.

Jako příklad je možné navrhnout filtr funkcí prohlížeče Microsoft Edge. Tento filtr funkcí by aktivoval všechny funkce, které jsou k němu připojené, pokud požadavek HTTP pochází z Microsoft Edge.

Konfigurace přepínače funkcí

Vývojáři v JavaScriptu běžně používají objekty nebo mapy jako primární datové struktury k reprezentaci konfigurací. Knihovna pro správu funkcí JavaScriptu podporuje oba přístupy konfigurace, což vývojářům poskytuje flexibilitu při výběru možnosti, která nejlépe vyhovuje jejich potřebám. FeatureManager může číst příznaky funkcí z různých typů konfigurace pomocí integrovaného ConfigurationObjectFeatureFlagProvider a 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);

Použití feature flagů z Azure App Configuration

Místo pevného kódování příznaků funkcí do aplikace doporučujeme zachovat příznaky funkcí mimo aplikaci a spravovat je samostatně. Tímto způsobem můžete kdykoli změnit stavy příznaků a tyto změny se projeví v aplikaci okamžitě. Služba Azure App Configuration poskytuje vyhrazené uživatelské rozhraní portálu pro správu všech funkčních přepínačů. Podívejte se na kurz.

Služba Azure App Configuration také doručuje přepínače funkcí vaší aplikaci přímo prostřednictvím klientské knihovny JavaScriptu @azure/app-configuration-provider. Následující příklad ukazuje, jak používat knihovnu.

Zprostředkovatel JavaScriptu konfigurace aplikace nabízí vlajkové funkce v objektu Map. Integrovaný ConfigurationMapFeatureFlagProvider pomáhá v tomto případě načíst příznaky funkcí.

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

Použijte Azure App Configuration k dynamickému řízení stavu přepínače funkcí

Azure App Configuration je nejen řešení pro externí ukládání a centralizovanou správu příznaků funkcí, ale také umožňuje dynamicky zapnout nebo vypnout příznaky funkcí.

Pokud chcete povolit dynamickou aktualizaci příznaků funkcí, musíte nakonfigurovat refresh vlastnost featureFlagOptions při načítání příznaků funkcí z 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);

Chcete-li získat nejnovější stav příznaku funkce, musíte zavolat metodu refresh.

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

Poznámka:

Další informace o tom, jak používat knihovnu pro správu funkcí s konfigurací Aplikace Azure, najdete v rychlém startu.

Deklarace příznaku funkce

Následující příklad ukazuje formát použitý k nastavení příznaků funkcí v souboru 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"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Oddíl feature_management se používá podle konvence k načtení nastavení funkčních příznaků. Oddíl feature_flags je seznam příznaků funkcí, které jsou načteny do knihovny. V předchozí části vidíme tři různé funkce. Vlastnosti definují své filtry vlastností pomocí vlastnosti client_filters, uvnitř conditions. Ve filtrech funkcí pro FeatureT vidíme, že enabled je true s nedefinovanými filtry, což vede k tomu, že FeatureT vždy vrací true. FeatureU je stejná jako FeatureT, ale s enabled, což má za následek, že funkce vždy vrací false. FeatureV určuje filtr funkcí s názvem Microsoft.TimeWindow. FeatureV je příkladem konfigurovatelného filtru funkcí. V příkladu vidíme, že filtr má parameters vlastnost. Vlastnost parameters slouží ke konfiguraci filtru. V tomto případě se konfigurují počáteční a koncové časy aktivní funkce.

Podrobné schéma oddílu feature_management najdete tady.

Pokročilé: Použití dvojtečky ':' je zakázáno v názvech příznaků funkcí.

Typ požadavku

Vlastnost requirement_type příznaku funkce se používá k určení, jestli filtry mají použít Any nebo All logiku při vyhodnocování stavu funkce. Pokud requirement_type není zadána, výchozí hodnota je Any.

  • Any znamená, že pouze jeden filtr musí být vyhodnocen jako true, aby byla funkce povolená.
  • All znamená, že každý filtr musí být vyhodnocen jako true, aby byla funkce povolená.

requirement_type All mění procházení. Za prvé, pokud nejsou k dispozici žádné filtry, je tato funkce zakázaná. Potom se filtry funkcí procházejí, dokud se některý z filtrů nerozhodne, že by měla být tato funkce zakázaná. Pokud žádný filtr neukazuje, že by funkce měla být zakázaná, považuje se za povolenou.

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

V předchozím příkladu FeatureW určuje requirement_type z All, což znamená, že všechny jeho filtry musí být vyhodnoceny jako true, aby byla funkce povolena. V tomto případě je tato funkce povolená pro 50 % uživatelů během zadaného časového intervalu.

Spotřeba

Základní forma správy funkcí kontroluje, jestli je povolený příznak funkce, a pak provádí akce na základě výsledku. Prostřednictvím metody FeatureManagerisEnabled se provádí kontrola stavu příznaku funkce.

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
}

Implementace filtru funkcí

Vytvoření filtru funkcí poskytuje způsob, jak povolit funkce na základě kritérií, která definujete. Aby bylo možné implementovat filtr funkcí, musí být implementováno IFeatureFilter rozhraní. IFeatureFilter name má vlastnost a metodu s názvem evaluate. Mělo by se použít name v konfiguraci pro odkazování na filtr vlastností v rámci příznaku vlastností. Když funkce specifikuje, že je možné ji povolit pro filtr funkcí, je volána metoda evaluate. Pokud se evaluate vrátí true, znamená to, že funkce by měla být povolená.

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

Následující fragment kódu ukazuje, jak implementovat přizpůsobený filtr funkcí s názvem MyCriteria.

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

Je potřeba registrovat vlastní filtr v rámci vlastnosti customFilters objektu FeatureManagerOptions předaného konstruktoru FeatureManager.

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

Parametrizované filtry funkcí

Některé filtry funkcí vyžadují parametry k určení, jestli má být funkce zapnutá nebo ne. Filtr funkcí prohlížeče může například zapnout funkci pro určitou sadu prohlížečů. Může být žádoucí, aby prohlížeče Edge a Chrome povolily funkci, zatímco Firefox ne. K tomu je možné navrhnout filtr funkcí tak, aby očekával parametry. Tyto parametry by byly zadány v konfiguraci funkce a v kódu by byly přístupné prostřednictvím parametru IFeatureFilterEvaluationContextIFeatureFilter.Evaluate.

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

IFeatureFilterEvaluationContext má vlastnost s názvem parameters. Tyto parametry představují nezpracovanou konfiguraci, pomocí které může filtr funkcí rozhodnout, jak vyhodnotit, jestli má být funkce povolená nebo ne. Pokud chcete znovu použít filtr funkcí prohlížeče jako příklad, filtr by mohl použít parameters k extrahování sady povolených prohlížečů, které by byly pro tuto funkci zadány, a pak zkontrolujte, jestli se požadavek odesílá z některého z těchto prohlížečů.

Použití kontextu aplikace pro vyhodnocení funkcí

Filtr funkcí může k vyhodnocení příznaku funkce potřebovat kontext aplikace za běhu. Kontext můžete předat jako parametr při volání isEnabled.

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

Filtr funkcí může využít kontext, který se předává při isEnabled zavolání. Kontext aplikace se předá jako druhý parametr IFeatureFilter.Evaluate.

Předdefinované filtry funkcí

Existují dva filtry funkcí, které jsou součástí FeatureManagement balíčku: TimeWindowFilter a TargetingFilter. Při vytváření FeatureManager se automaticky přidají všechny zabudované filtry funkcí.

Každý z předdefinovaných filtrů funkcí má vlastní parametry. Tady je seznam filtrů funkcí spolu s příklady.

Microsoft.TimeWindow

Tento filtr poskytuje možnost povolit funkci na základě časového intervalu. Pokud je zadán pouze End, bude funkce považována za zapnutou až do toho okamžiku. Pokud je zadáno pouze Start, bude tato funkce považována za zapnutou ve všech bodech po uplynutí této doby.

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

Časové období je možné nakonfigurovat tak, aby se pravidelně opakovalo. To může být užitečné ve scénářích, kdy může být potřeba zapnout funkci během období nízkého nebo vysokého provozu dne nebo určitého dne v týdnu. Pokud chcete rozbalit jednotlivé časové intervaly na opakující se časová období, mělo by být v parametru Recurrence zadáno pravidlo opakování.

Poznámka:

Start a End musí být zadány oba, aby bylo možné povolit 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"
                }
            }
        }
    }
]

Nastavení Recurrence se skládá ze dvou částí: Pattern (jak často se časové okno opakuje) a Range (jak dlouho se vzorec opakování opakuje).

Opakování

Existují dva možné typy opakování: Daily a Weekly. Například časové okno může opakovat "každý den", "každé tři dny", "každé pondělí" nebo "každý druhý pátek".

V závislosti na typu jsou určitá pole Pattern povinná, nepovinná nebo ignorováná.

  • Daily

    Způsob denního opakování způsobí opakování časového intervalu na základě počtu dnů mezi jednotlivými výskyty.

    Vlastnost Relevance Popis
    Type Povinné Musí být nastavena na Daily.
    Interval Volitelný Určuje počet dní mezi každým výskytem. Výchozí hodnota je 1.
  • Weekly

    Způsob týdenního opakování způsobí opakování časového intervalu ve stejný den nebo dny v týdnu na základě počtu týdnů mezi jednotlivými sadami výskytů.

    Vlastnost Relevance Popis
    Type Povinné Musí být nastavena na Weekly.
    DaysOfWeek Povinné Určuje, ve kterých dnech v týdnu dojde k události.
    Interval Volitelný Určuje počet týdnů mezi každou sadou výskytů. Výchozí hodnota je 1.
    FirstDayOfWeek Volitelný Určuje, který den se považuje za první den v týdnu. Výchozí hodnota je Sunday.

    Následující příklad opakuje časové okno každé druhé pondělí a úterý.

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

Poznámka:

Start musí být platný první výskyt, který odpovídá vzoru opakování. Kromě toho doba trvání časového intervalu nemůže být delší, než jak často k němu dochází. Například je neplatné, aby se každý den opakoval 25hodinový časový interval.

Rozsah opakování

Existují tři možné typy rozsahu opakování: NoEndEndDate a Numbered.

  • NoEnd

    Rozsah NoEnd způsobí, že opakování proběhne neomezeně dlouho.

    Vlastnost Relevance Popis
    Type Povinné Musí být nastavena na NoEnd.
  • EndDate

    Rozsah EndDate způsobí, že časový interval nastane ve všech dnech, které odpovídají příslušnému vzoru do koncového data.

    Vlastnost Relevance Popis
    Type Povinné Musí být nastavena na EndDate.
    Datum ukončení Povinné Určuje datum, kdy se má model přestat používat. Pokud počáteční čas posledního výskytu spadá před koncové datum, je možné, že koncový čas tohoto výskytu přesahuje jeho rámec.

    Následující příklad opakuje časové intervaly každý den, dokud se poslední výskyt nestane 1. dubna 2024.

    "Start": "Fri, 22 Mar 2024 18:00:00 GMT",
    "End": "Fri, 22 Mar 2024 20:00:00 GMT",
    "Recurrence":{
        "Pattern": {
            "Type": "Daily",
            "Interval": 1
        },
        "Range": {
            "Type": "EndDate",
            "EndDate": "Mon, 1 Apr 2024 20:00:00 GMT"
        }
    }
    
  • Numbered

    Rozsah Numbered způsobí, že časový interval nastane pevný početkrát (podle vzoru).

    Vlastnost Relevance Popis
    Type Povinné Musí být nastavena na Numbered.
    PočetVýskytů Povinné Určuje počet výskytů.

    Následující příklad zopakuje časové okno v pondělí a úterý, dokud nedojde ke třem výskytům, které postupně nastanou 1. dubna (pondělí), 2. dubna (úterý) a 8. dubna (pondělí).

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

Chcete-li vytvořit pravidlo opakování, musíte zadat obě Pattern a Range. Jakýkoli typ vzoru může fungovat s libovolným typem rozsahu.

Pokročilý: Posun časového pásma vlastnosti Start se použije na nastavení opakování.

Microsoft.Targeting

Tento filtr poskytuje možnost povolit funkci cílové cílové skupině. Podrobné vysvětlení cílení je vysvětleno v části cílení níže. Parametry filtru zahrnují Audience objekt, který popisuje uživatele, skupiny, vyloučené uživatele/skupiny a výchozí procento uživatelské základny, které by měly mít přístup k této funkci. Každý objekt skupiny, který je uveden v oddílu Groups , musí také určit, jaké procento členů skupiny by mělo mít přístup. Pokud je uživatel zadaný v oddílu Exclusion , buď přímo, nebo pokud je uživatel ve vyloučené skupině, je tato funkce zakázaná. Jinak platí, že pokud je uživatel zadán přímo v oddílu Users, nebo pokud je uživatel zahrnut v procentech zavádění některé skupiny, nebo pokud spadá do výchozího procenta zavádění, bude mít tento uživatel povolenou funkci.

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

Cílení

Cílení je strategie správy funkcí, která vývojářům umožňuje postupně zavádět nové funkce do uživatelské základny. Strategie je založená na konceptu cílení na skupinu uživatelů, kteří se označují jako cílová skupina. Cílová skupina se skládá z konkrétních uživatelů, skupin, vyloučených uživatelů/skupin a určeného procenta celé uživatelské základny. Skupiny, které jsou součástí cílové skupiny, je možné dále rozdělit do procent jejich celkových členů.

Následující kroky ukazují příklad postupného zavedení nové funkce Beta:

  1. Jednotlivým uživatelům Jeff a Alicia jsou udělen přístup k beta verzi.
  2. Jiný uživatel, Mark, žádá, aby se přihlásil a je zahrnutý.
  3. Do beta verze je zahrnuta dvacet procent skupiny, která se označuje jako "Ring1".
  4. Počet uživatelů v okruhu "Ring1" zahrnutých v beta verzi se zvýší na 100 procent.
  5. Součástí beta verze je pět procent uživatelské základny.
  6. Procento zavedení se nastaví na 100 procent a funkce je plně zavedená.

Tato strategie pro zavádění funkce je součástí knihovny prostřednictvím zahrnutého filtru funkcí Microsoft.Targeting .

Cílení na uživatele s kontextem cílení

Filtr cílení spoléhá na kontext cílení a vyhodnocuje, jestli má být funkce zapnutá. Tento kontext cílení obsahuje informace, jako je například aktuálně vyhodnocený uživatel a v jakých skupinách se uživatel nachází. Kontext cílení musí být předán přímo při zavolání isEnabled.

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

Vyloučení z cílení

Při definování cílové skupiny mohou být uživatelé a skupiny vyloučeni z cílové skupiny. Vyloučení jsou užitečná pro to, když se funkce zavádí do skupiny uživatelů, ale z zavedení je potřeba vyloučit několik uživatelů nebo skupin. Vyloučení je definováno přidáním seznamu uživatelů a skupin do Exclusion vlastnosti cílové skupiny.

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

V předchozím příkladu je funkce povolena pro uživatele pojmenované Jeff a Alicia. Je také povolená pro uživatele ve skupině s názvem Ring0. Pokud je však uživatel pojmenován Mark, je funkce zakázaná bez ohledu na to, jestli jsou ve skupině Ring0 nebo ne. Vyloučení mají přednost před zbytkem filtru cílení.

Cílení ve webové aplikaci

V tomto ukázkovém projektu je k dispozici ukázková webová aplikace, která používá filtr funkcí cílení.

Ve webových aplikacích, zejména těch s více komponentami nebo vrstvami, se předávání cílového kontextu (userId a groups) při každém ověření stavové vlajky může stát těžkopádným a repetitivním. Tento scénář se označuje jako "ambientní kontext cílení", kde informace o identitě uživatele jsou již k dispozici v kontextu aplikace (například v datech relace nebo v kontextu ověřování), je však třeba, aby byly přístupné pro vyhodnocení správy funkcí v celé aplikaci.

ITargetingContextAccessor

Knihovna poskytuje řešení prostřednictvím ITargetingContextAccessor vzoru.

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

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

Místo explicitního předávání s každým voláním isEnabled nebo getVariant kontextu cílení můžete poskytnout funkci, která ví, jak načíst informace o cílení aktuálního uživatele z kontextu vaší aplikace.

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

Tento model je užitečný zejména ve webových aplikacích na straně serveru, kde může být kontext uživatele dostupný v oboru požadavku nebo v klientských aplikacích, kde se identita uživatele spravuje centrálně.

Použití AsyncLocalStorage pro kontext požadavku

Jednou z běžných výzev při implementaci přístupového vzoru kontextu cílení je udržení kontextu žádosti v rámci asynchronního řetězce volání. Ve Node.js webových aplikacích jsou informace o identitě uživatele obvykle k dispozici v objektu požadavku, ale jakmile zadáte asynchronní operace, stanou se nepřístupné.

Node.js poskytuje AsyncLocalStorage z modulu async_hooks k vyřešení tohoto problému. Vytvoří úložiště, které se uchovává napříč asynchronními operacemi ve stejném logickém kontextu – ideální pro zachování dat požadavků v průběhu celého životního cyklu žádosti.

Tady je postup implementace přístupového objektu kontextu cílení pomocí AsyncLocalStorage v expresní aplikaci:

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

Varianty

Když se do aplikace přidají nové funkce, může přijít čas, kdy má funkce několik různých navrhovaných možností návrhu. Běžným řešením pro rozhodování o návrhu je určitá forma testování A/B, která zahrnuje poskytnutí jiné verze funkce různým segmentům uživatelské základny a výběru verze na základě interakce uživatele. V této knihovně je tato funkce povolena reprezentací různých konfigurací funkce s variantami.

Varianty umožňují, aby se příznak funkce stal více než jednoduchým příznakem zapnuto/vypnuto. Varianta představuje hodnotu příznaku funkce, který může být řetězec, číslo, logická hodnota nebo dokonce objekt konfigurace. Příznak funkce, který deklaruje varianty, by měl definovat za jakých okolností se má každá varianta použít, která je podrobněji popsána v části Přidělování variant .

Získání varianty s kontextem cílení

Pro každou funkci lze variantu načíst pomocí metody FeatureManager objektu getVariant. Přiřazení varianty závisí na uživateli, kterého se právě vyhodnocuje, a informace se získávají z kontextu cílení, který jste předali. Pokud jste zaregistrovali accessor kontextu cílení pro FeatureManager, kontext cílení se z něj automaticky načte. Můžete ho ale přesto přepsat ručním předáváním kontextu cílení při volání 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

Deklarace funkčního příznaku varianty

Ve srovnání s normálními příznaky funkcí mají příznaky varianty dvě další vlastnosti: variants a allocation. Vlastnost variants je pole, které obsahuje varianty definované pro tuto funkci. Vlastnost allocation definuje, jak mají být tyto varianty přiděleny pro tuto funkci. Stejně jako deklarování normálních příznaků funkcí můžete v souboru JSON nastavit příznaky variant funkcí. Tady je příklad variantního přepínače funkce.

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

Definování variant

Každá varianta má dvě vlastnosti: název a konfiguraci. Název se používá k odkazování na konkrétní variantu a konfigurace je hodnota této varianty. Konfiguraci lze nastavit pomocí configuration_value vlastnosti. configuration_value je vložená konfigurace, která může být řetězec, číslo, logická hodnota nebo objekt konfigurace. Pokud configuration_value není zadána, vrácená vlastnost varianty configuration je undefined.

Seznam všech možných variant je definován pro každou funkci v rámci variants vlastnosti.

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

Přidělování variant

Proces přidělování variant funkce je určen allocation vlastností funkce.

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

Nastavení allocation funkce má následující vlastnosti:

Vlastnost Popis
default_when_disabled Určuje, která varianta se má použít, když se vyžaduje varianta, zatímco je tato funkce považována za zakázanou.
default_when_enabled Určuje, která varianta se má použít, když je varianta požadována, zatímco je funkce považována za povolenou a uživateli nebyla přiřazena žádná jiná varianta.
user Určuje variantu a seznam uživatelů, kterým má být tato varianta přiřazena.
group Určuje variantu a seznam skupin. Varianta je přiřazena, pokud je uživatel alespoň v jedné ze skupin.
percentile Určuje variantu a procentní rozsah, do kterého musí zapadat vypočítané procento uživatele, aby mu byla tato varianta přiřazena.
seed Hodnota, na které jsou založeny procentuální výpočty percentile . Procento výpočtu pro konkrétního uživatele bude stejné ve všech funkcích, pokud se použije stejná seed hodnota. Pokud není zadána žádná seed hodnota, vytvoří se výchozí počáteční hodnota na základě názvu funkce.

Pokud tato funkce není povolená, správce funkcí přiřadí variantu označenou aktuálnímu default_when_disabled uživateli, což je Small v tomto případě.

Pokud je tato funkce povolená, správce funkcí zkontroluje přidělení user, group, a percentile ve zmíněném pořadí, aby přiřadil variantu. V tomto konkrétním příkladu platí, že pokud je vyhodnocený uživatel pojmenovaný Marsha, ve skupině s názvem Ring1nebo se stane, že uživatel spadá mezi 0 a 10. percentil, pak je zadaná varianta přiřazena uživateli. V takovém případě by variantu Big vrátili všichni přiřazení uživatelé. Pokud se žádné z těchto přidělení neshoduje, přiřadí se uživateli varianta default_when_enabled , což je Small.

Logika přidělení je podobná filtru funkcí Microsoft.Targeting , ale existují některé parametry, které jsou přítomné v cílení, které nejsou v přidělení, a naopak. Výsledky cílení a přidělování nesouvisí.

Přepsání povoleného stavu variantou

Varianty můžete použít k přepsání povoleného stavu příznaku funkce. Přepsání dává variantám příležitost rozšířit vyhodnocení funkční vlajky. Při volání is_enabled příznaku s variantami správce funkcí zkontroluje, jestli je varianta přiřazená aktuálnímu uživateli nakonfigurovaná tak, aby přepsala výsledek. Přepsání se provádí pomocí volitelné vlastnosti varianty status_override. Ve výchozím nastavení je tato vlastnost nastavena na None, což znamená, že varianta nemá vliv na to, zda je příznak považován za povolený nebo zakázaný. Nastavení status_override na Enabled umožňuje, aby zvolená varianta přepsala příznak, který se má povolit. Nastavení status_override na Disabled poskytuje opačnou funkčnost, a tím pádem zakáže příznak při výběru varianty. Funkci s nastaveným stavem enabledfalse nelze přepsat.

Pokud používáte příznak funkce s binárními variantami, status_override může být tato vlastnost užitečná. Umožňuje vám i nadále používat rozhraní API, jako je is_enabled ve vaší aplikaci a zároveň těžit z nových funkcí, které přinášejí varianty, jako je přidělení percentilu a počáteční semeno.

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

Ve výše uvedeném příkladu je funkce vždy povolená. Pokud je aktuální uživatel v počítaném rozsahu percentilu 10 až 20, vrátí se varianta On . V opačném případě se varianta Off vrátí a protože status_override je rovna Disabled, funkce bude nyní považována za zakázanou.

Telemetrie

Když je nasazena změna příznaku funkce, je často důležité analyzovat její vliv na aplikaci. Tady je například několik otázek, které mohou nastat:

  • Jsou moje vlajky povolené nebo zakázané, jak bylo očekáváno?
  • Mají cíloví uživatelé přístup k určité funkci podle očekávání?
  • Jakou variantu vidí konkrétní uživatel?

Na tyto typy otázek je možné odpovědět prostřednictvím emisí a analýzy událostí vyhodnocení příznaků funkcí.

Povolení telemetrie

Ve výchozím nastavení příznaky funkcí nevygenerují telemetrii. Pokud chcete publikovat telemetrii pro daný příznak funkce, musí příznak deklarovat, že má povolené emise telemetrie.

U příznaků funkcí definovaných ve formátu JSON se povolení provádí pomocí telemetry vlastnosti.

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

Výše uvedený fragment kódu definuje příznak funkce s názvem MyFeatureFlag , který je povolený pro telemetrii. Vlastnost telemetry objektu enabled je nastavena na true. Hodnota vlastnosti enabled musí být true, aby bylo možné publikovat telemetrii příznaku.

Část telemetry příznaku funkce má následující vlastnosti:

Vlastnost Popis
enabled Určuje, jestli má být telemetrie publikována pro příznak funkce.
metadata Kolekce párů klíč-hodnota modelovaná jako slovník, která se dá použít k připojení vlastních metadat o feature flagu u vyhodnocovacích událostí.

Vlastní publikování telemetrie

Při vytváření onFeatureEvaluated můžete zaregistrovat funkci zpětného volání FeatureManager. Toto zpětné volání se provede pokaždé, když je vyhodnocen příznak funkce a pro tento příznak je povolena telemetrie. Funkce zpětného volání převezme výsledek vyhodnocení funkce jako parametr.

Následující příklad ukazuje, jak implementovat vlastní funkci zpětného volání pro odesílání telemetrie s informacemi extrahovanými z výsledku vyhodnocení funkce a zaregistrovat ji do správce funkcí.

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

Integrace s Application Insights

Knihovna pro správu funkcí JavaScriptu poskytuje balíčky rozšíření, které se integrují se sadami SDK Application Insights .

Application Insights nabízí různé sady SDK pro webové a Node.js scénáře. Vyberte správné balíčky rozšíření pro vaši aplikaci.

Pokud se vaše aplikace spustí v prohlížeči, nainstalujte "@microsoft/feature-management-applicationinsights-browser" balíček. Následující příklad ukazuje, jak můžete vytvořit integrovaného vydavatele telemetrie Application Insights a zaregistrovat ho do správce funkcí.

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

Vydavatel telemetrie odesílá vlastní události FeatureEvaluation do Application Insights, když se vyhodnotí příznak funkce, který má povolenou telemetrii. Vlastní událost se řídí schématem FeatureEvaluationEvent .

Cílení na procesor telemetrie

Pokud jste implementovali ITargetingContextAccessor, můžete pomocí integrovaného procesoru telemetrie Application Insights automaticky připojit informace o ID cílení ke všem telemetriím voláním funkce 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)
);

Tím se zajistí, že každá položka telemetrie odeslaná do Application Insights zahrnuje informace o ID cílení uživatele (userId a skupiny), které vám umožní korelovat využití příznaků funkcí s konkrétními uživateli nebo skupinami v analýzách.

Pokud používáte procesor telemetrie cíle, místo volání trackEvent metody poskytované balíčkem pro správu funkcí můžete metodu trackEvent přímo volat ze sady Application Insights SDK. Informace o ID cílení se automaticky připojí k customDimensions telemetrii vlastní události.

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

Další kroky

Pokud chcete zjistit, jak ve svých aplikacích používat příznaky funkcí, pokračujte na následující rychlé návody.

Pokud se chcete dozvědět, jak používat filtry funkcí, pokračujte následujícími kurzy.