Správa funkcí Pythonu
Knihovna pro správu funkcí Pythonu 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 Pythonu, aby bylo možné tyto funkce odhalit.
Příznaky funkcí umožňují aplikacím Pythonu dynamicky zapnout nebo vypnout funkce. 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í Pythonu:
Běžná konvence správy funkcí
Nízká bariéra pro vstup
- Podporuje nastavení příznaku funkce JSON.
Správa životnosti příznaků funkcí
- Hodnoty konfigurace se mohou měnit v reálném čase; příznaky funkcí můžou být konzistentní v rámci celého požadavku.
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í Pythonu je opensourcová. Další informace najdete v úložišti GitHub.
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říznaku funkce
Slovník Pythonu se používá k definování příznaků funkcí. Slovník se skládá z názvů funkcí jako klíčů a objektů příznaků jako hodnot. Objekt příznaku funkce je slovník, který obsahuje conditions
klíč, který samotný klíč obsahuje client_filters
. Klíč client_filters
je seznam filtrů funkcí, které slouží k určení, jestli má být tato funkce povolená.
Deklarace příznaku funkce
Knihovna pro správu funkcí podporuje json jako zdroj příznaku funkce. Níže máme příklad formátu použitého 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"
}
}
]
}
}
]
}
}
Část feature_management
dokumentu JSON se používá konvencí k načtení nastavení příznaku funkce. 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. Funkce definují filtry funkcí pomocí client_filters
vlastnosti uvnitř conditions
. V filtrech funkcí pro FeatureT
, vidíme enabled
, že je zapnutý bez definovaných filtrů, což vede FeatureT
vždy k true
vrácení . FeatureU
je stejná jako funkce, ale FeatureT
enabled
výsledkem je false
, ž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.
Upřesnit: Použití dvojtečky :je zakázáno v názvech příznaků funkce.
Deklarace zapnuto/vypnuto
Následující fragment kódu ukazuje alternativní způsob definování funkce, kterou lze použít pro funkce zapnuto/vypnuto.
{
"feature_management": {
"feature_flags": [
{
"id": "FeatureT",
"enabled": "true"
},
{
"id": "FeatureX",
"enabled": "false"
}
]
}
}
Requirement_type
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á.
All
Změna requirement_type
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 určuje hodnotu requirement_type
All
, což znamená, FeatureW
ž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.
Využití
Základní forma správy funkcí kontroluje, jestli je povolený příznak funkce, a pak provádí akce na základě výsledku. Kontrola stavu příznaku funkce se provádí prostřednictvím FeatureManager
is_enabled
metody.
…
feature_manager = FeatureManager(feature_flags)
…
if feature_manager.is_enabled("FeatureX"):
# Do something
FeatureManager
Zadaným feature_flags
příznakem AzureAppConfigurationProvider
může být buď slovník příznaků funkcí, nebo slovník.
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 FeatureFilter
rozhraní. FeatureFilter
má jednu metodu s názvem evaluate
. Když funkce určuje, že je možné ji povolit pro filtr funkcí, evaluate
volá se metoda. Pokud evaluate
se vrátí true
, znamená to, že by funkce měla být povolená.
Následující fragment kódu ukazuje, jak přidat přizpůsobený filtr MyCustomFilter
funkcí .
feature_manager = FeatureManager(feature_flags, feature_filters=[MyCustomFilter()])
Filtry funkcí jsou registrovány jejich poskytnutím vlastnosti feature_filters
při vytváření FeatureManager
. Pokud vlastní filtr funkcí potřebuje jakýkoli kontext, lze je předat při volání is_enabled
pomocí kwargs
.
Atribut aliasu filtru
Pokud je filtr funkcí zaregistrovaný pro příznak funkce, název filtru se ve výchozím nastavení používá jako alias.
Identifikátor filtru funkce lze přepsat pomocí parametru @FeatureFilter.alias("MyFilter")
. Filtr funkcí lze dekorovat tímto atributem a deklarovat název, který by se měl použít v konfiguraci pro odkazování na tento filtr funkcí v rámci příznaku funkce.
Chybějící filtry funkcí
Pokud je funkce nakonfigurovaná tak, aby byla povolená pro konkrétní filtr funkcí a tento filtr funkcí není zaregistrovaný, ValueError
při vyhodnocení funkce se vyvolá výjimka.
Předdefinované filtry funkcí
Existují dva filtry funkcí, které jsou součástí FeatureManagement
balíčku: TimeWindowFilter
a TargetingFilter
.
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ána pouze End
tato funkce, bude tato funkce do té doby považována za zapnutou. Pokud je zadána pouze Start
tato funkce, bude funkce považovaná za všechny body 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"
}
}
]
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 uvedení skupiny nebo pokud uživatel spadá do výchozího procenta uvedení, 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:
- Jednotlivým uživatelům Jeff a Alicia je udělen přístup k beta verzi.
- Jiný uživatel, Mark, žádá, aby se přihlásil a je zahrnutý.
- Do beta verze je zahrnuta dvacet procent skupiny, která se označuje jako "Ring1".
- Počet uživatelů okruhu 1 zahrnutých v beta verzi se zhrouží až na 100 procent.
- Pět procent uživatelské základny je součástí beta verze.
- Procento zavedení se přeplní až na 100 procent a funkce se kompletně zavádí.
Tato strategie pro zavádění funkce je integrovaná do knihovny prostřednictvím zahrnutého filtru funkcí Microsoft.Targeting .
Cílení na uživatele
Buď může být uživatel zadán přímo v is_enabled
hovoru, nebo TargetingContext
lze použít k určení uživatele a volitelné skupiny.
# 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"]))
Vyloučení 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í.
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. Testování A/B 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 .
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
Získání variant
Pro každou funkci je možné načíst variantu FeatureManager
pomocí metody '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
Vrácená varianta závisí na uživateli, který se právě vyhodnocuje, a že informace jsou získány z instance TargetingContext
.
Deklarace příznaku funkce Variant
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 příznaku funkce varianty.
{
"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 None
.
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_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"
}
]
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 procento rozsahu, do kterého se musí přiřadit vypočítané procento uživatele. |
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 user
group
percentile
a přidělení v dané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 Ring1
nebo 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í příznaku funkce. 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 status_override
varianty . 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
pro Enabled
povolení varianty, pokud je zvoleno, přepsat příznak, který se má povolit. Nastavení status_override
pro Disabled
poskytnutí opačných funkcí, a proto zakázání příznaku při výběru varianty. Funkci se stavem enabled
false
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 pokračovat v používání rozhraní API, jako is_enabled
je například ve vaší aplikaci, a zároveň využívat nové funkce, které jsou součástí variant, jako je přidělení percentilu a počáteční hodnota.
{
"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
Při nasazení změny 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 příznaky povolené nebo zakázané podle očekávání?
- 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í. Tato knihovna volitelně umožňuje AzureMonitor
generování telemetrie trasování během vyhodnocení příznaku funkce prostřednictvím OpenTelemetry
.
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 enabled
vlastnosti musí být true
k publikování telemetrie 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 příznaku funkce k vyhodnocení událostí. |
Kromě toho při vytváření FeatureManager
musí být zpětné volání registrováno pro zpracování telemetrických událostí. Toto zpětné volání se volá pokaždé, když se vyhodnotí příznak funkce a pro tento příznak je povolená telemetrie.
feature_manager = FeatureManager(feature_flags, on_feature_evaluated=publish_telemetry)
Telemetrie Application Insights
Knihovna pro správu funkcí poskytuje integrovaného vydavatele telemetrie, který odesílá data vyhodnocení příznaků funkcí do Application Insights. Pokud chcete povolit Application Insights, můžete knihovnu pro správu funkcí nainstalovat se službou Azure Monitor prostřednictvím pip install FeatureManagement[AzureMonitor]
. Tento příkaz nainstaluje azure-monitor-events-extension
balíček, který se používá ke stylu telemetrie do Application Insights pomocí OpenTelemetry.
Poznámka:
Balíček azure-monitor-events-extension
přidá telemetrii jenom do kanálu Open Telemetry. Registrace Application Insights se stále vyžaduje.
from azure.monitor.opentelemetry import configure_azure_monitor
configure_azure_monitor(
connection_string="InstrumentationKey=00000000-0000-0000-0000-000000000000"
)
Vlastní publikování telemetrie
Vzhledem k tomu, že zpětné volání telemetrie je funkce, je možné ji přizpůsobit tak, aby publikovala telemetrii do libovolného požadovaného cíle. Například telemetrie se může publikovat do služby protokolování, databáze nebo vlastní služby telemetrie.
Když se vyhodnotí příznak funkce a povolí se telemetrie, správce funkcí zavolá zpětné volání telemetrie pomocí parametru EvaluationEvent
. EvaluationEvent
obsahuje následující vlastnosti:
Značka | Popis |
---|---|
feature |
Použitý příznak funkce. |
user |
ID uživatele, které se používá k cílení. |
enabled |
Určuje, jestli je příznak funkce vyhodnocen jako povolený. |
Variant |
Přiřazená varianta. |
VariantAssignmentReason |
Důvod přiřazení varianty |
Další kroky
Pokud chcete zjistit, jak ve svých aplikacích používat příznaky funkcí, pokračujte následujícími rychlými starty.
Pokud se chcete dozvědět, jak používat filtry funkcí, pokračujte následujícími kurzy.