Dela via


Hantering av Python-funktioner

Funktionshantering

Funktionshantering

Med Pythons funktionshanteringsbibliotek 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 Python-kodmönster för att göra det möjligt att exponera dessa funktioner.

Funktionsflaggor är ett sätt för Python-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 Python-funktionshanteringsbiblioteket:

  • En vanlig konvention för funktionshantering

  • Låg barriär för inträde

    • Stöder konfiguration av JSON-funktionsflagga
  • Livslängdshantering för funktionsflagga

    • Konfigurationsvärden kan ändras i realtid. funktionsflaggor kan vara konsekventa i hela begäran
  • Enkla till komplexa scenarier som omfattas

    • Växla på/av-funktioner via deklarativ konfigurationsfil
    • Utvärdera funktionstillstånd dynamiskt baserat på anrop till server

    Python-funktionshanteringsbiblioteket är öppen källkod. Mer information finns på GitHub-lagringsplatsen.

Funktionsflaggor

Funktionsflaggor består av två delar, ett namn och en lista över funktionsfilter som används för att aktivera funktionen.

Funktionsfilter

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

En Python-ordlista används för att definiera funktionsflaggor. Ordlistan består av funktionsnamn som nycklar och objekt för funktionsflagga som värden. Objekt för funktionsflagga är en ordlista som innehåller en conditions nyckel som i sig innehåller client_filters nyckeln. Nyckeln client_filters är en lista över funktionsfilter som används för att avgöra om funktionen ska aktiveras.

Deklaration av funktionsflagga

Funktionshanteringsbiblioteket stöder json som en funktionsflaggakälla. Nedan visas ett exempel på 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 i json-dokumentet används av konventionen för att läsa in 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 FeatureTser enabled vi att är på utan definierade filter, vilket resulterar i FeatureT att true alltid returnera . 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.

Av/på-deklaration

Följande kodfragment visar ett alternativt sätt att definiera en funktion som kan användas för av/på-funktioner.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": "true"
            },
            {
                "id": "FeatureX",
                "enabled": "false"
            }
        ]
    }
}

Requirement_type

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 .

  • Any innebär att endast ett filter behöver utvärderas till sant för att funktionen ska aktiveras.
  • All innebär att varje filter måste utvärderas till sant för att funktionen ska aktiveras.

En requirement_type av All ändrar bläddringarna. 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 FeatureManagermetoden 's is_enabled .

…
feature_manager = FeatureManager(feature_flags)
…
if feature_manager.is_enabled("FeatureX"):
    # Do something

Den feature_flags som tillhandahålls till FeatureManager kan antingen vara AzureAppConfigurationProvider eller en ordlista med funktionsflaggor.

Implementera ett funktionsfilter

Genom att skapa ett funktionsfilter kan du aktivera funktioner baserat på kriterier som du definierar. För att implementera ett funktionsfilter FeatureFilter måste gränssnittet implementeras. FeatureFilter har en enda metod med namnet evaluate. 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.

Följande kodfragment visar hur du lägger till ett anpassat funktionsfilter MyCustomFilter.

feature_manager = FeatureManager(feature_flags, feature_filters=[MyCustomFilter()])

Funktionsfilter registreras genom att ge dem till egenskapen feature_filters när du skapar FeatureManager. Om ett anpassat funktionsfilter behöver någon kontext kan de skickas in när du anropar is_enabled med .kwargs

Filteraliasattribut

När ett funktionsfilter registreras för en funktionsflagga används namnet på filtret som standard som alias.

Identifieraren för funktionsfiltret kan åsidosättas med hjälp @FeatureFilter.alias("MyFilter")av . Ett funktionsfilter kan dekoreras med det här attributet för att deklarera det namn som ska användas i konfigurationen för att referera till det här funktionsfiltret i en funktionsflagga.

Funktionsfilter saknas

Om en funktion har konfigurerats för att aktiveras för ett specifikt funktionsfilter och funktionsfiltret inte har registrerats utlöses ett ValueError undantag när funktionen utvärderas.

Inbyggda funktionsfilter

Det finns två funktionsfilter som medföljer FeatureManagement paketet: TimeWindowFilter, och TargetingFilter.

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 beaktas funktionen på 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"
        }
    }
]     

Microsoft.Targeting

Det här filtret ger möjlighet att aktivera en funktion för en målgrupp. En detaljerad förklaring av målinriktningen förklaras i målavsnittet 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 den inkluderade procentandelen av någon av gruppdistributionerna, eller om användaren hamnar i standardprocenten för distribution 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"
                    ]
                }
            }
        }
    }
]

Sök mål

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:

  1. Enskilda användare Jeff och Alicia beviljas åtkomst till betaversionen
  2. En annan användare, Mark, ber att få anmäla sig och inkluderas.
  3. Tjugo procent av en grupp som kallas "Ring1"-användare ingår i betaversionen.
  4. Antalet "Ring1"-användare som ingår i betaversionen ökas till 100 procent.
  5. Fem procent av användarbasen ingår i betaversionen.
  6. Distributionsprocenten ökar till 100 procent och funktionen distribueras 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

Antingen kan en användare anges direkt i anropet is_enabled eller så kan en TargetingContext användas för att ange användaren och den valfria gruppen.

# Directly specifying the user
result = is_enabled(feature_flags, "test_user")

# Using a TargetingContext
result = is_enabled(feature_flags, TargetingContext(user_id="test_user", 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.

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. A/B-testning innebär att tillhandahålla en annan version av funktionen till olika segment i 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 .

class Variant:
    def __init__(self, name: str, configuration: Any):
        self._name = name
        self._configuration = configuration

    @property
    def name(self) -> str:
        """
        The name of the variant.
        :rtype: str
        """
        return self._name

    @property
    def configuration(self) -> Any:
        """
        The configuration of the variant.
        :rtype: Any
        """
        return self._configuration

Hämta varianter

För varje funktion kan en variant hämtas med metoden FeatureManager's get_variant .

…
variant = print(feature_manager.get_variant("TestVariants", TargetingContext(user_id="Adam"))

variantConfiguration = variant.configuration;

// Do something with the resulting variant and its configuration

Varianten som returneras är beroende av att användaren för närvarande utvärderas och att informationen hämtas från en instans av TargetingContext.

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 Noneden returnerade variantens Configuration egenskap .

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_enabled": "Small", 
    "default_when_disabled": "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:

Property 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, groupoch percentile i den 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. Åsidosättande ger varianter en möjlighet att utöka utvärderingen av en funktionsflagga. 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. Inställningen status_override tillåter att Enabled varianten, när den väljs, åsidosätter en flagga som ska aktiveras. Inställningen status_override ger Disabled motsatt funktionalitet och inaktiverar därför flaggan när varianten väljs. En funktion med tillståndet enabled false kan inte åsidosättas.

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 utsläpp och analys av funktionsflaggans utvärderingshändelser. Med det här biblioteket kan du också skapa AzureMonitor spårningstelemetri under utvärdering av funktionsflagga via OpenTelemetry.

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 telemetry enabled 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:

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

När du skapar FeatureManagermåste dessutom ett återanrop registreras för att hantera telemetrihändelser. Det här återanropet anropas när en funktionsflagga utvärderas och telemetri aktiveras för den flaggan.

feature_manager = FeatureManager(feature_flags, on_feature_evaluated=publish_telemetry)

Application Insights-telemetri

Funktionshanteringsbiblioteket innehåller en inbyggd telemetriutgivare som skickar utvärderingsdata för funktionsflaggan till Application Insights. För att aktivera Application Insights kan funktionshanteringsbiblioteket installeras med Azure Monitor via pip install FeatureManagement[AzureMonitor]. Det här kommandot installerar azure-monitor-events-extension paketet, som används för att formatera telemetri till Application Insights med hjälp av OpenTelemetry.

Kommentar

Paketet azure-monitor-events-extension lägger bara till telemetrin i pipelinen Öppna telemetri. Registrering av Application Insights krävs fortfarande.

from azure.monitor.opentelemetry import configure_azure_monitor

configure_azure_monitor(
        connection_string="InstrumentationKey=00000000-0000-0000-0000-000000000000"
    )

Anpassad telemetripublicering

Eftersom telemetriåteranropet är en funktion kan den anpassas för att publicera telemetri till önskat mål. Telemetri kan till exempel publiceras till en loggningstjänst, en databas eller en anpassad telemetritjänst.

När en funktionsflagga utvärderas och telemetri aktiveras anropar funktionshanteraren telemetriåteranropet med en EvaluationEvent parameter. EvaluationEvent innehåller följande egenskaper:

Tagg beskrivning
feature Funktionsflaggan som används.
user Användar-ID:t som används för mål.
enabled Om funktionsflaggan utvärderas som aktiverad.
Variant Den tilldelade varianten.
VariantAssignmentReason Anledningen till att varianten tilldelas.

Nästa steg

Om du vill lära dig hur du använder funktionsflaggor i dina program fortsätter du till följande snabbstarter.

Om du vill lära dig hur du använder funktionsfilter fortsätter du till följande självstudier.