Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La libreria di gestione delle funzionalità JavaScript consente di sviluppare ed esporre funzionalità dell'applicazione in base ai flag di funzionalità. Una volta sviluppata una nuova funzionalità, molte applicazioni hanno requisiti speciali, ad esempio relativamente a quando la funzionalità deve essere abilitata e in quali condizioni. Questa libreria consente di definire queste relazioni e di integrarsi anche in modelli di codice JavaScript comuni per rendere possibile l'esposizione di queste funzionalità.
I flag di funzionalità consentono alle applicazioni JavaScript di attivare o disattivare dinamicamente le funzionalità. Gli sviluppatori possono usare flag di funzionalità in casi d'uso semplici, ad esempio istruzioni condizionali.
Ecco alcuni dei vantaggi dell'uso della libreria di gestione delle funzionalità JavaScript:
- Una convenzione comune per la gestione delle funzionalità
- Barriera bassa all'ingresso
- Supporta sia gli oggetti JSON che le origini dei flag di funzionalità basate su mapping
- Supporta l'utilizzo sia in Node.js che in ambienti browser
- Gestione del ciclo di vita dei flag di funzionalità con Azure App Configuration
- I valori di configurazione possono cambiare in tempo reale
- Scenari semplici e complessi trattati
- Attivare/disattivare le funzionalità tramite il file di configurazione dichiarativo
- Valutare dinamicamente lo stato della funzionalità in base alla chiamata al server
La libreria di gestione delle funzionalità JavaScript è open source. Per altre informazioni, visitare il repository GitHub.
Nota
È consigliabile usare la libreria di gestione delle funzionalità insieme a Configurazione app di Azure. Configurazione app di Azure è una soluzione per la gestione centralizzata delle impostazioni delle applicazioni e dei flag di funzionalità. Per altri dettagli, vedere questa sezione.
Flag di funzionalità
I flag di funzionalità sono costituiti da due parti, un nome e un elenco di filtri di funzionalità usati per attivare la funzionalità.
Filtri di funzionalità
I filtri di funzionalità definiscono uno scenario per il momento in cui è necessario abilitare una funzionalità. Quando viene valutato se una funzionalità è attivata o disattivata, il relativo elenco di filtri di funzionalità viene attraversato fino a quando uno dei filtri non decide che la funzionalità deve essere abilitata. A questo punto, la funzionalità viene considerata abilitata e l'attraversamento dei filtri di funzionalità si arresta. Se nessun filtro di funzionalità indica che la funzionalità deve essere abilitata, questa viene considerata disattivata.
Ad esempio, è possibile progettare un filtro di funzionalità del browser Microsoft Edge. Questo filtro di funzionalità attiverà tutte le funzionalità a cui è collegato, purché una richiesta HTTP provenga da Microsoft Edge.
Configurazione del flag di funzionalità
In JavaScript gli sviluppatori usano in genere oggetti o mappe come strutture di dati primari per rappresentare le configurazioni. La libreria di gestione delle funzionalità JavaScript supporta entrambi gli approcci di configurazione, offrendo agli sviluppatori la flessibilità di scegliere l'opzione più adatta alle proprie esigenze.
FeatureManager può leggere i flag di funzionalità da diversi tipi di configurazione usando i valori predefiniti ConfigurationObjectFeatureFlagProvider e ConfigurationMapFeatureFlagProvider.
const config = new Map([
["feature_management", {
"feature_flags": [
{
"id": "FeatureT",
"enabled": true
},
{
"id": "FeatureU",
"enabled": false
}
]
}],
["some other configuration", " some value"]
]);
import { ConfigurationMapFeatureFlagProvider, FeatureManager } from "@microsoft/feature-management";
const featureProvider = new ConfigurationMapFeatureFlagProvider(config);
const featureManager = new FeatureManager(featureProvider);
Usare i flag di funzionalità da Configurazione app di Azure
Invece di impostare come hardcoded i flag di funzionalità nell'applicazione, è consigliabile mantenere i flag di funzionalità all'esterno dell'applicazione e gestirli separatamente. In questo modo è possibile modificare gli stati dei flag in qualsiasi momento e applicare immediatamente tali modifiche nell'applicazione. Il servizio di Configurazione app di Azure offre un'interfaccia utente del portale dedicata per la gestione di tutti i flag di funzionalità. Guarda il tutorial.
Il servizio di configurazione app Azure fornisce anche i flag di funzionalità all'applicazione direttamente tramite la relativa libreria client JavaScript @azure/app-configuration-provider. Nell'esempio seguente viene illustrato come usare la libreria .
Il provider JavaScript di Configurazione app fornisce flag di funzionalità in un oggetto Map. In questo caso, la funzionalità predefinita ConfigurationMapFeatureFlagProvider consente di caricare i flag di funzionalità.
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);
Usare Configurazione App di Azure per gestire dinamicamente lo stato del flag delle funzionalità
Configurazione app di Azure non è solo una soluzione per esternalizzare l'archiviazione e la gestione centralizzata dei flag di funzionalità, ma consente anche di attivare/disattivare dinamicamente i flag di funzionalità.
Per abilitare l'aggiornamento dinamico dei flag di funzionalità, è necessario configurare la proprietà refresh di featureFlagOptions quando si caricano i flag di funzionalità dalla Configurazione app di Azure.
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);
È necessario chiamare il metodo refresh per ottenere lo stato del flag di funzionalità più recente.
await appConfig.refresh(); // Refresh to get the latest feature flags
const isBetaEnabled = await featureManager.isEnabled("Beta");
console.log(`Beta is enabled: ${isBetaEnabled}`);
Nota
Per altre informazioni su come usare la libreria di gestione delle funzionalità con Configurazione app di Azure, vedere la guida introduttiva.
Dichiarazione dei flag di funzionalità
L'esempio seguente illustra il formato usato per configurare i flag di funzionalità in un file 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 sezione feature_management viene usata per convenzione per caricare le impostazioni dei flag di funzionalità. La sezione feature_flags è un elenco dei flag di funzionalità caricati nella libreria. Nella sezione precedente vengono visualizzate tre differenti funzionalità. Le funzionalità definiscono i relativi filtri di funzionalità usando la proprietà client_filters, all'interno di conditions. Nei filtri di funzionalità per FeatureT, si noterà che enabled è true senza filtri definiti, con FeatureT che restituisce sempre true.
FeatureU è uguale a FeatureT ma con enabled è false e la funzionalità restituisce sempre false.
FeatureV specifica un filtro di funzionalità denominato Microsoft.TimeWindow.
FeatureV è un esempio di filtro di funzionalità configurabile. Nell'esempio è possibile osservare che il filtro ha una proprietà parameters. La proprietà parameters viene utilizzata per configurare il filtro. In questo caso, vengono configurati gli orari di inizio e fine per la funzionalità da attivare.
Lo schema dettagliato della sezione feature_management è disponibile qui.
Avanzate: l'utilizzo dei due punti ':' non è consentito nei nomi dei flag di funzionalità.
Tipo di requisito
La proprietà requirement_type di un flag di funzionalità viene utilizzata per determinare se i filtri devono usare l logica Any o All durante la valutazione dello stato di una funzionalità. Se requirement_type non è specificato, il valore predefinito è Any.
-
Anysignifica che, per abilitare la funzionalità, è necessario che un solo filtro venga valutato come vero. -
Allindica che ogni filtro deve essere valutato come vero per abilitare la funzionalità.
Un oggetto requirement_type di All modifica l'attraversamento. In primo luogo, se non sono presenti filtri, la funzionalità è disabilitata. I filtri di funzionalità vengono quindi attraversati fino a quando uno dei filtri non decide che la funzionalità deve essere disabilitata. Se nessun filtro indica che la funzionalità deve essere disabilitata, questa viene considerata abilitata.
{
"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"
}
}
]
}
},
]
}
}
Nell'esempio precedente, FeatureW specifica un requirement_type di All, ovvero tutti i relativi filtri devono essere valutati come vero per abilitare la funzionalità. In questo caso, la funzionalità è abilitata per il 50% degli utenti durante l'intervallo di tempo specificato.
Consumo
La forma di base di gestione delle funzionalità consiste nel verificare se un flag di funzionalità è abilitato ed eseguire azioni in base al risultato. Il controllo dello stato di un flag di funzionalità viene eseguito tramite il metodo FeatureManager di 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
}
Implementazione di un filtro di funzionalità
La creazione di un filtro di funzionalità consente di abilitare le funzionalità in base ai criteri definiti dall'utente. Per implementare un filtro di funzionalità, è necessario implementare l'interfaccia IFeatureFilter.
IFeatureFilter ha una name proprietà e un metodo denominato evaluate. Il name dovrebbe essere utilizzato nella configurazione per riferirsi al filtro di funzionalità all'interno di una bandiera delle funzionalità. Quando una funzionalità specifica che può essere abilitata per un filtro di funzionalità, viene chiamato il metodo evaluate. Se evaluate restituisce true, significa che la funzionalità deve essere abilitata.
interface IFeatureFilter {
name: string;
evaluate(context: IFeatureFilterEvaluationContext, appContext?: unknown): boolean | Promise<boolean>;
}
Il frammento di codice seguente illustra come implementare un filtro di funzionalità personalizzato con il nome MyCriteria.
class MyCriteriaFilter {
name = "MyCriteria";
evaluate(context, appContext) {
if (satisfyCriteria()) {
return true;
}
else {
return false;
}
}
}
È necessario registrare il filtro personalizzato nella customFilters proprietà dell'oggetto FeatureManagerOptions passato al FeatureManager costruttore.
const featureManager = new FeatureManager(ffProvider, {
customFilters: [
new MyCriteriaFilter() // add custom feature filters under FeatureManagerOptions.customFilters
]
});
Filtri delle funzionalità con parametri
Alcuni filtri di funzionalità richiedono parametri per decidere se una funzionalità deve essere attivata o meno. Ad esempio, un filtro di funzionalità del browser può attivare una funzionalità per un determinato set di browser. Potrebbe essere necessario che i browser Edge e Chrome abilitino una funzionalità, mentre per Firefox non è così. A tale scopo, è possibile progettare un filtro di funzionalità per prevedere parametri. Questi parametri verranno specificati nella configurazione della funzionalità e nel codice sarebbero accessibili tramite il parametro IFeatureFilterEvaluationContext di IFeatureFilter.Evaluate.
interface IFeatureFilterEvaluationContext {
featureName: string;
parameters?: unknown;
}
IFeatureFilterEvaluationContext ha una proprietà denominata parameters. Questi parametri rappresentano una configurazione non elaborata che il filtro delle funzionalità può usare per decidere come valutare se la funzionalità deve essere abilitata o meno. Per usare nuovamente il filtro delle funzionalità del browser come esempio, il filtro può usare parameters per estrarre un set di browser consentiti che verrebbero specificati per la funzionalità e controllare se la richiesta viene inviata da uno di questi browser.
Usare il contesto dell'applicazione per la valutazione delle funzionalità
Un filtro di funzionalità potrebbe richiedere il contesto dell'applicazione di runtime per valutare un flag di funzionalità. È possibile passare il contesto come parametro quando si chiama isEnabled.
featureManager.isEnabled("Beta", { userId : "Sam" })
Il filtro di funzionalità può sfruttare il contesto passato quando viene chiamato isEnabled. Il contesto dell'applicazione verrà passato come secondo parametro di IFeatureFilter.Evaluate.
Filtri di funzionalità predefiniti
Esistono due filtri di funzionalità disponibili con il FeatureManagement pacchetto: TimeWindowFilter e TargetingFilter. Tutti i filtri di funzionalità predefiniti verranno aggiunti per impostazione predefinita durante la costruzione di FeatureManager.
Ognuno dei filtri di funzionalità predefiniti ha i propri parametri. Ecco l'elenco dei filtri delle funzionalità insieme agli esempi.
Microsoft.TimeWindow
Questo filtro offre la possibilità di abilitare una funzionalità in base a una finestra temporale. Se viene specificato solo End, la funzionalità viene considerata attiva fino a quel momento. Se viene specificato solo Start, la funzionalità viene considerata attiva in tutti i momenti successivi a tale periodo.
"client_filters": [
{
"name": "Microsoft.TimeWindow",
"parameters": {
"Start": "Wed, 01 May 2019 13:59:59 GMT",
"End": "Mon, 01 Jul 2019 00:00:00 GMT"
}
}
]
L'intervallo di tempo può essere configurato per la ricorsione periodica. Può essere utile per gli scenari in cui potrebbe essere necessario attivare una funzionalità durante un periodo di traffico basso o elevato di un giorno o di determinati giorni di una settimana. Per espandere la singola finestra temporale in intervalli di tempo ricorrenti, è necessario specificare la regola di ricorrenza nel Recurrence parametro .
Nota
Start e End devono essere entrambi specificati per abilitare 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"
}
}
}
}
]
Le Recurrence impostazioni sono costituite da due parti: Pattern (con quale frequenza si ripete l'intervallo di tempo) e Range (per quanto tempo il criterio di ricorrenza viene ripetuto).
Criterio di ricorrenza
Esistono due possibili tipi di criteri di ricorrenza: Daily e Weekly. Ad esempio, un intervallo di tempo potrebbe ripetere "ogni giorno", "ogni tre giorni", "ogni lunedì" o "ogni altro venerdì".
A seconda del tipo, alcuni campi di Pattern sono obbligatori, facoltativi o ignorati.
DailyIl criterio di ricorrenza giornaliera determina la ripetizione dell'intervallo di tempo in base a un numero di giorni tra ogni occorrenza.
Proprietà Pertinenza Descrizione Tipo Obbligatorio Deve essere impostato su Daily.Intervallo Opzionale Specifica il numero di giorni tra ogni occorrenza. Il valore predefinito è 1. WeeklyIl criterio di ricorrenza settimanale fa sì che l'intervallo di tempo si ripeta nello stesso giorno o giorno della settimana, in base al numero di settimane tra ogni set di occorrenze.
Proprietà Pertinenza Descrizione Tipo Obbligatorio Deve essere impostato su Weekly.DaysOfWeek Obbligatorio Specifica in quali giorni della settimana si verifica l'evento. Intervallo Opzionale Specifica il numero di settimane tra ciascuna serie di occorrenze. Il valore predefinito è 1. FirstDayOfWeek Opzionale Specifica quale giorno viene considerato il primo giorno della settimana. Il valore predefinito è Sunday.L'esempio seguente ripete l'intervallo di tempo ogni lunedì e martedì
"Pattern": { "Type": "Weekly", "Interval": 2, "DaysOfWeek": ["Monday", "Tuesday"] }
Nota
Start deve essere una prima occorrenza valida che si adatta al criterio di ricorrenza. Inoltre, la durata dell'intervallo di tempo non può essere più lunga della frequenza con cui si verifica. Ad esempio, non è valido avere un intervallo di tempo di 25 ore che si ripete ogni giorno.
L'intervallo di ricorrenza
Esistono tre possibili tipi di intervallo di ricorrenza: NoEnde EndDateNumbered.
NoEndL'intervallo
NoEndfa sì che la ricorrenza avvenga indefinitamente.Proprietà Pertinenza Descrizione Tipo Obbligatorio Deve essere impostato su NoEnd.EndDateL'intervallo
EndDatefa sì che l'intervallo di tempo si verifichi in tutti i giorni che soddisfano il modello applicabile fino alla data di fine.Proprietà Pertinenza Descrizione Tipo Obbligatorio Deve essere impostato su EndDate.EndDate Obbligatorio Specifica la data e l'ora per interrompere l'applicazione dello schema. Fino a quando l'ora di inizio dell'ultima occorrenza cade prima della data di fine, l'ora di fine di tale occorrenza può estendersi oltre. L'esempio seguente ripeterà l'intervallo di tempo ogni giorno fino all'ultima occorrenza del 1° aprile 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" } }NumberedL'intervallo
Numberedfa sì che l'intervallo di tempo si verifichi un numero fisso di volte (in base al modello).Proprietà Pertinenza Descrizione Tipo Obbligatorio Deve essere impostato su Numbered.NumeroDiOccorrenze Obbligatorio Specifica il numero di occorrenze. L'esempio seguente ripeterà l'intervallo di tempo lunedì e martedì fino a quando non saranno presenti tre occorrenze, le quali si verificano rispettivamente il 1° aprile (lun), il 2 aprile (mar) e l'8 aprile (lun).
"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 } }
Per creare una regola di ricorrenza, è necessario specificare sia Pattern che Range. Qualsiasi tipo di modello può essere utilizzato con qualsiasi tipo di intervallo.
Avanzato: L'offset del fuso orario della Start proprietà viene applicato alle impostazioni di ricorrenza.
Microsoft.Targeting
Questo filtro offre la possibilità di abilitare una funzionalità per un pubblico di destinazione. Una spiegazione approfondita del targeting è illustrata nella sezione di targeting seguente. I parametri di filtro includono un oggetto Audience che descrive utenti, gruppi, utenti/gruppi esclusi e una percentuale predefinita della base di utenti che deve avere accesso alla funzionalità. Ogni oggetto gruppo elencato nella sezione Groups deve specificare anche la percentuale di accesso ai membri del gruppo. Se nella sezione Exclusion viene specificato un utente, sia direttamente che se l'utente si trova in un gruppo escluso, la funzionalità è disabilitata. In caso contrario, se un utente viene specificato direttamente nella sezione Users, se l'utente si trova nella percentuale di implementazione inclusa di uno dei gruppi o se rientra nella percentuale di implementazione predefinita, tale utente avrà la funzionalità abilitata.
"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"
]
}
}
}
}
]
Destinazione
Il targeting è una strategia di gestione delle funzionalità che consente agli sviluppatori di implementare progressivamente nuove funzionalità alla propria base di utenti. La strategia si basa sul concetto di destinazione di un set di utenti noto come gruppo di destinatari. Un gruppo di destinatari è costituito da utenti, gruppi specifici, utenti/gruppi esclusi e una percentuale designata dell'intera base di utenti. I gruppi inclusi nel gruppo di destinatari possono essere suddivisi ulteriormente in percentuali dei membri totali.
I passaggi seguenti illustrano un esempio di implementazione progressiva per una nuova funzionalità "Beta":
- Ai singoli utenti Jeff e Alicia viene concesso l'accesso alla versione Beta.
- Un altro utente, Mark, richiede di aderire ed è incluso.
- Il venti percento di un gruppo noto come utenti "Ring1" è incluso nella Beta.
- Il numero di utenti "Ring1" inclusi nella beta è salito fino al 100%.
- Il 5% della base utente è incluso nella versione Beta.
- La percentuale di implementazione viene incrementata fino al 100% e la funzionalità viene implementata completamente.
Questa strategia per l'implementazione di una funzionalità è integrata nella libreria tramite il filtro di funzionalità Microsoft.Targeting incluso.
Targeting di un utente con contesto di targeting
Il filtro di destinazione si basa su un contesto di destinazione per valutare se una funzionalità deve essere attivata. Questo contesto di destinazione contiene informazioni quali l'utente attualmente in fase di valutazione e i gruppi in cui si trova l'utente. Il contesto di destinazione deve essere passato direttamente quando isEnabled viene chiamato.
featureManager.isEnabled("Beta", { userId: "Aiden", groups: ["Ring1"] })
Esclusione di targeting
Quando si definisce un gruppo di destinatari, gli utenti e i gruppi possono essere esclusi dal gruppo di destinatari. Le esclusioni sono utili quando viene implementata una funzionalità a un gruppo di utenti, ma è necessario escludere alcuni utenti o gruppi dall'implementazione. L'esclusione viene definita aggiungendo un elenco di utenti e gruppi alla proprietà Exclusion del gruppo di destinatari.
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0,
"Exclusion": {
"Users": [
"Mark"
]
}
}
Nell'esempio precedente la funzionalità è abilitata per gli utenti denominati Jeff e Alicia. È anche abilitata per gli utenti nel gruppo denominato Ring0. Tuttavia, se l'utente è denominato Mark, la funzionalità è disabilitata, indipendentemente dal fatto che si trovino nel gruppo Ring0 o meno. Le esclusioni hanno la priorità rispetto al resto del filtro di destinazione.
Destinazione in un'applicazione Web
In questo progetto di esempio è disponibile un'applicazione Web di esempio che usa il filtro di funzionalità di destinazione.
Nelle applicazioni Web, in particolare quelle con più componenti o livelli, il passaggio del contesto di destinazione (userId e groups) a ogni controllo del flag di funzionalità può diventare complesso e ripetitivo. Questo scenario viene definito "contesto di destinazione ambientale", in cui le informazioni sull'identità utente sono già disponibili nel contesto dell'applicazione ,ad esempio nei dati di sessione o nel contesto di autenticazione, ma devono essere accessibili alle valutazioni di gestione delle funzionalità in tutta l'applicazione.
ITargetingContextAccessor
La libreria fornisce una soluzione tramite il ITargetingContextAccessor modello .
interface ITargetingContext {
userId?: string;
groups?: string[];
}
interface ITargetingContextAccessor {
getTargetingContext: () => ITargetingContext | undefined;
}
Anziché passare in modo esplicito il contesto di destinazione in ogni chiamata isEnabled o getVariant, puoi fornire una funzione che sappia come recuperare le informazioni di destinazione dell'utente corrente, dal contesto dell'applicazione.
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");
Questo modello è particolarmente utile nelle applicazioni Web lato server in cui il contesto utente può essere disponibile in un ambito di richiesta o nelle applicazioni client in cui l'identità utente viene gestita centralmente.
Uso di AsyncLocalStorage per il contesto della richiesta
Una sfida comune quando si implementa il modello di accesso al contesto di destinazione consiste nel mantenere il contesto della richiesta durante una catena di chiamate asincrone. In Node.js applicazioni Web, le informazioni sull'identità utente sono in genere disponibili nell'oggetto richiesta, ma diventa inaccessibile dopo aver immesso operazioni asincrone.
Node.js fornisce AsyncLocalStorage dal async_hooks modulo per risolvere questo problema. Crea un archivio che persiste tra le operazioni asincrone all'interno dello stesso "contesto" logico, perfetto per mantenere i dati delle richieste nell'intero ciclo di vita della richiesta.
Ecco come implementare una funzione di accesso al contesto di destinazione usando AsyncLocalStorage in un'applicazione rapida:
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 || []
};
}
};
Varianti
Quando vengono aggiunte nuove funzionalità a un'applicazione, potrebbe verificarsi un momento in cui una funzionalità include differenti opzioni di progettazione proposte. Una soluzione comune per decidere una progettazione è una forma di test A/B, che implica la fornitura di una versione differente della funzionalità a differenti segmenti della base di utenti e la scelta di una versione in base all'interazione dell'utente. In questa libreria, la funzionalità è abilitata rappresentando differenti configurazioni di una funzionalità con varianti.
Le varianti consentono a un flag di funzionalità di diventare più di un semplice flag on/off. Una variante rappresenta un valore di un flag di funzionalità che può essere una stringa, un numero, un valore booleano o anche un oggetto di configurazione. Un flag di funzionalità che dichiara le varianti deve definire in quali circostanze deve essere usata ogni variante, descritta in modo più dettagliato nella sezione Allocazione varianti.
Ottenere una variante con contesto di targeting
Per ogni funzionalità, è possibile recuperare una variante usando il metodo FeatureManager del getVariant. L'assegnazione delle varianti dipende dall'utente che è attualmente in fase di valutazione e le informazioni vengono ottenute dal contesto di targeting che hai inserito. Se è stata registrata una funzione di accesso del contesto di destinazione a FeatureManager, il contesto di destinazione verrà recuperato automaticamente da essa. Tuttavia, è comunque possibile eseguirne l'override passando manualmente il contesto di destinazione quando si chiama 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
Dichiarazione delle varianti dell'indicatore di funzionalità
Rispetto ai normali flag di funzionalità, i flag di funzionalità delle varianti hanno due proprietà in più: variants e allocation. La proprietà variants è un array che contiene le varianti definite per questa funzionalità. La proprietà allocation definisce la modalità di allocazione di queste varianti per la funzionalità. Come per dichiarare i normali flag di funzionalità, è possibile configurare flag di funzionalità delle varianti in un file JSON. Di seguito è riportato un esempio di flag di funzionalità delle varianti.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
Definizione di varianti
Ogni variante ha due proprietà: un nome e una configurazione. Il nome viene usato per fare riferimento a una variante specifica e la configurazione è il valore di tale variante. La configurazione può essere impostata usando la proprietà configuration_value.
configuration_value è una configurazione inline che può essere una stringa, un numero, un valore booleano o un oggetto di configurazione. Se configuration_value non viene specificato, la proprietà configuration della variante restituita è undefined.
Un elenco di tutte le possibili varianti viene definito per ogni funzionalità nella proprietà variants.
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
Allocazione di varianti
Il processo di allocazione delle varianti di una funzionalità è determinato dalla proprietà allocation della funzionalità.
"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"
}
]
L'impostazione allocation di una funzionalità ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
default_when_disabled |
Specifica quale variante deve essere utilizzata quando viene richiesta una variante mentre la funzionalità viene considerata disabilitata. |
default_when_enabled |
Specifica quale variante deve essere utilizzata quando viene richiesta una variante mentre la funzionalità viene considerata abilitata e nessun'altra variante è stata assegnata all'utente. |
user |
Specifica una variante e un elenco di utenti a cui deve essere assegnata tale variante. |
group |
Specifica una variante e un elenco di gruppi. La variante viene assegnata se l'utente si trova in almeno uno dei gruppi. |
percentile |
Specifica una variante e un intervallo percentuale in base al quale deve essere assegnata la percentuale calcolata dell'utente. |
seed |
Valore su cui si basano i calcoli percentuali per percentile. Il calcolo percentuale per un utente specifico sarà lo stesso in tutte le funzionalità se viene usato lo stesso valore seed. Se non viene specificato alcun valore seed, viene creato un valore di inizializzazione predefinito in base al nome della funzionalità. |
Se la funzionalità non è abilitata, il manager delle funzionalità assegna la variante contrassegnata come default_when_disabled all'utente corrente, in questo caso Small.
Se la funzionalità è abilitata, il manager delle funzionalità verifica le allocazioni user, group e percentile in tale ordine al fine di assegnare una variante. Per questo particolare esempio, se l'utente valutato è denominato Marsha nel gruppo denominato Ring1, o se l'utente si trova tra lo 0 e il 10° percentile, la variante specificata viene assegnata all'utente. In questo caso, tutti gli utenti assegnati restituirebbero la variante Big. Se nessuna di queste allocazioni corrisponde, all'utente viene assegnata la variante default_when_enabled, ovvero Small.
La logica di allocazione è simile al filtro di funzionalità Microsoft.Targeting, ma esistono alcuni parametri presenti nella destinazione che non sono nell'allocazione e viceversa. I risultati della destinazione e dell'allocazione non sono correlati.
Override dello stato abilitato con una variante
È possibile usare varianti per eseguire l'override dello stato abilitato di un flag di funzionalità. L'override consente alle varianti la possibilità di estendere la valutazione di un flag di funzionalità. Quando si chiama is_enabled su un flag con varianti, il gestore delle funzionalità verificherà se la variante assegnata all'utente corrente è configurata per eseguire l'override del risultato. Questa operazione viene eseguita usando la proprietà variante facoltativa status_override. Per impostazione predefinita, questa proprietà è impostata su None, il che significa che la variante non influisce sul fatto che il flag sia considerato abilitato o disabilitato. L'impostazione status_override su Enabled consente alla variante, se scelta, di eseguire l'override di un flag da abilitare. L'impostazione status_override su Disabled fornisce la funzionalità opposta, disabilitando quindi il flag quando viene scelta la variante. Non è possibile eseguire l'override di una funzionalità con stato enabled di false.
Se si usa un flag di funzionalità con varianti binarie, la proprietà status_override può essere utile. Consente di continuare a usare API come is_enabled nell'applicazione, sfruttando al tempo stesso le nuove funzionalità fornite con varianti, ad esempio allocazione percentile e seeding.
{
"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"
}
]
}
Nell'esempio precedente la funzionalità è sempre abilitata. Se l'utente corrente si trova nell'intervallo percentile calcolato compreso tra 10 e 20, viene restituita la variante On. In caso contrario, viene restituita la variante Off e, poiché status_override è uguale a Disabled, la funzionalità verrà ora considerata disabilitata.
Telemetria
Quando viene distribuita una modifica del flag di funzionalità, è spesso importante analizzarne l'effetto su un'applicazione. Ecco alcune domande che possono verificarsi, ad esempio:
- I flag sono abilitati/disabilitati come previsto?
- Gli utenti di destinazione ottengono l'accesso a una determinata funzionalità come previsto?
- Quale variante viene visualizzata da un utente specifico?
Questi tipi di domande possono essere risposte tramite l'emissione e l'analisi degli eventi di valutazione dei flag di funzionalità.
Abilitazione della telemetria
Per impostazione predefinita, i flag di funzionalità non hanno telemetria emessa. Per pubblicare i dati di telemetria per un determinato flag di funzionalità, il flag MUST dichiara che è abilitato per l'emissione di dati di telemetria.
Per i flag di funzionalità definiti in JSON, l'abilitazione viene eseguita usando la proprietà telemetry.
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
Il frammento di codice precedente definisce un flag di funzionalità denominato MyFeatureFlag abilitato per i dati di telemetria. La proprietà telemetry dell'oggetto enabled è impostata su true. Il valore della proprietà enabled deve essere true per pubblicare i dati di telemetria per il flag.
La sezione telemetry di un flag di funzionalità ha le proprietà seguenti:
| Proprietà | Descrizione |
|---|---|
enabled |
Specifica se i dati di telemetria devono essere pubblicati per il flag di funzionalità. |
metadata |
Raccolta di coppie chiave-valore, modellate come dizionario, che possono essere usate per allegare metadati personalizzati relativi al flag di funzionalità agli eventi di valutazione. |
Pubblicazione di telemetria personalizzata
È possibile registrare una onFeatureEvaluated funzione di callback durante la creazione di FeatureManager. Questo callback viene chiamato ogni volta che viene valutato un flag di funzionalità e la telemetria è abilitata per tale flag. La funzione di callback accetta il risultato della valutazione delle funzionalità come parametro.
L'esempio seguente illustra come implementare una funzione di callback personalizzata per inviare dati di telemetria con le informazioni estratte dal risultato della valutazione delle funzionalità e registrarla nel gestore delle funzionalità.
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});
Integrazione con Application Insights
La libreria di gestione delle funzionalità JavaScript fornisce pacchetti di estensione che si integrano con Gli SDK di Application Insights .
Application Insights offre SDK diversi per scenari Web e Node.js . Selezionare i pacchetti di estensione corretti per l'applicazione.
Se l'applicazione viene eseguita nel browser, installare il "@microsoft/feature-management-applicationinsights-browser" pacchetto. L'esempio seguente illustra come creare un server di pubblicazione di telemetria di Application Insights predefinito e registrarlo nel gestore delle funzionalità.
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'editore di telemetria invia FeatureEvaluation eventi personalizzati ad Application Insights quando viene valutato un flag di funzionalità abilitato con telemetria. L'evento personalizzato segue lo schema FeatureEvaluationEvent .
Targeting del processore di telemetria
Se è stato implementato ITargetingContextAccessor, è possibile usare il processore di telemetria predefinito di Application Insights per associare automaticamente le informazioni sull'ID di destinazione a tutti i dati di telemetria chiamando la createTargetingTelemetryProcessor funzione .
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)
);
Ciò garantisce che ogni elemento di telemetria inviato ad Application Insights includa le informazioni sull'ID di destinazione dell'utente (userId e gruppi), consentendo di correlare l'utilizzo dei flag di funzionalità a utenti o gruppi specifici nell'analisi.
Se si usa il processore di telemetria di destinazione, anziché chiamare il trackEvent metodo fornito dal pacchetto di gestione delle funzionalità, è possibile chiamare direttamente il trackEvent metodo da Application Insights SDK. Le informazioni sull'ID di destinazione verranno associate automaticamente a customDimensions di telemetria dell'evento personalizzato.
// 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" });
Passaggi successivi
Per informazioni su come usare i flag di funzionalità nelle applicazioni, continuare con gli avvi rapidi.
Per informazioni su come usare i filtri di funzionalità, continuare con le esercitazioni seguenti.