Python 功能管理
Python 功能管理程式庫提供一種方式,可讓您根據功能旗標來開發和公開應用程式功能。 一旦開發新功能之後,許多應用程式都有特殊需求,例如何時應該啟用此功能,以及要在哪些情況下啟用此功能。 此程式庫提供一種方式來定義這些關聯,同時還能整合至常見的 Python 程式碼模式,讓公開這些功能成為可能。
功能旗標會為 Python 應用程式提供一種方式來動態開啟或關閉功能。 開發人員可以在簡單的使用案例 (例如,條件陳述式) 中使用功能旗標。
以下是使用 Python 功能管理程式庫的一些優點:
功能管理的常見慣例
進入門檻較低
- 支援 JSON 功能旗標設定
功能旗標存留期管理
- 組態值可以即時變更;功能旗標在整個要求中可以保持一致
涵蓋簡單至複雜的案例
- 透過宣告式組態檔切換開啟/關閉功能
- 根據對伺服器的呼叫動態評估功能的狀態
Python 功能管理程式庫是開放原始碼。 如需詳細資訊,請造訪 GitHub 存放庫。
功能旗幟
功能旗標是由兩個部分所組成,一個名稱和一份用來開啟功能的功能篩選清單。
功能篩選
功能篩選會定義何時應啟用功能的案例。 評估功能是否開啟或關閉時,會周遊其功能篩選清單,直到其中一個篩選條件決定應啟用功能為止。 此時,功能會被視為已啟用且周遊功能篩選會停止。 如果沒有功能篩選指出應該啟用功能,則會將其視為已停用。
例如,可以設計 Microsoft Edge 瀏覽器功能篩選。 只要 HTTP 要求來自 Microsoft Edge,此功能篩選就會啟用其所附加的任何功能。
功能旗標組態
Python 字典可用來定義功能旗標。 此字典會由作為索引鍵的功能名稱和作為值的功能旗標物件所組成。 功能旗標物件是包含 conditions
索引鍵的字典,其本身包含 client_filters
索引鍵。 client_filters
索引鍵是用來判斷是否應啟用功能的功能篩選清單。
功能旗標宣告
功能管理程式庫支援 JSON 作為功能旗標來源。 以下是用來在 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"
}
}
]
}
}
]
}
}
JSON 文件的 feature_management
區段會由慣例用來載入功能旗標設定。 feature_flags
區段是載入至程式庫的功能旗標清單。 在上一節中,我們看到三個不同的功能。 功能會使用 client_filters
屬性 (而非 conditions
) 來定義其功能篩選。 在 FeatureT
的功能篩選中,我們看到 enabled
處於開啟狀態且未定義任何篩選,因而導致 FeatureT
一律傳回 true
。 FeatureU
與 FeatureT
相同,但 enabled
為 false
,導致該功能一律傳回 false
。 FeatureV
指定名為 Microsoft.TimeWindow
的功能篩選。 FeatureV
是可設定功能篩選的範例。 我們可以在範例中看到篩選條件具有 parameters
屬性。 parameters
屬性可用來設定篩選。 在此情況下,會設定要成為作用中功能的開始和結束時間。
您可以在這裡找到 feature_management
區段的詳細結構描述。
進階:功能旗標名稱中禁止使用冒號 ':'。
開啟/關閉宣告
下列程式碼片段示範定義可用於開啟/關閉功能之功能的替代方式。
{
"feature_management": {
"feature_flags": [
{
"id": "FeatureT",
"enabled": "true"
},
{
"id": "FeatureX",
"enabled": "false"
}
]
}
}
Requirement_type
功能旗標的 requirement_type
屬性可用來判斷篩選條件在評估功能的狀態時,是否應該使用 Any
或 All
邏輯。 如果未指定 requirement_type
,則預設值為 Any
。
Any
表示只有一個篩選條件需要評估為 true,即可啟用此功能。All
表示每個篩選條件都必須評估為 true,才能啟用此功能。
All
的 requirement_type
會變更周遊。 首先,如果沒有篩選條件,則會停用此功能。 然後,功能篩選會周遊,直到其中一個篩選條件決定應該停用功能為止。 如果沒有篩選條件表示應該停用功能,系統會將其視為已啟用。
{
"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"
}
}
]
}
},
]
}
}
在上述範例中,FeatureW
指定了 All
的 requirement_type
,這表示其所有篩選條件都必須評估為 true,才能啟用此功能。 在此情況下,此功能會在指定的時間範圍內針對 50% 的使用者啟用。
耗用
功能管理的基本形式是檢查功能旗標是否已啟用,然後根據結果執行動作。 檢查功能旗標的狀態會透過 FeatureManager
的 is_enabled
方法來完成。
…
feature_manager = FeatureManager(feature_flags)
…
if feature_manager.is_enabled("FeatureX"):
# Do something
提供給 FeatureManager
的 feature_flags
可以是 AzureAppConfigurationProvider
或功能旗標的字典。
實作功能篩選
建立功能篩選可讓您根據您定義的準則來啟用功能。 若要實作功能篩選,必須實作 FeatureFilter
介面。 FeatureFilter
具有名為 evaluate
的單一方法。 當功能指定其可以針對功能篩選啟用時,就會呼叫 evaluate
方法。 如果 evaluate
傳回 true
,表示應該啟用功能。
下列程式碼片段示範如何新增自訂功能篩選 MyCustomFilter
。
feature_manager = FeatureManager(feature_flags, feature_filters=[MyCustomFilter()])
藉由在建立 FeatureManager
時,將功能篩選提供給 feature_filters
屬性進行註冊。 如果自訂功能篩選需要任何內容,則可在使用 kwargs
呼叫 is_enabled
時傳入它們。
篩選別名屬性
為功能旗標註冊功能篩選時,預設會使用篩選的名稱作為別名。
您可以使用 @FeatureFilter.alias("MyFilter")
來覆寫功能篩選的識別碼。 功能篩選可以使用這個屬性裝飾,宣告應該用於組態的名稱,以在功能旗標內參考這項功能篩選。
遺漏功能篩選
如果已將某個功能設定為針對特定功能篩選啟用,且該功能篩選尚未註冊,則會在評估該功能時引發 ValueError
例外狀況。
內建功能篩選
FeatureManagement
套件隨附的兩個功能篩選:TimeWindowFilter
和 TargetingFilter
。
每個內建功能篩選都有自己的參數。 以下是功能篩選清單以及範例。
Microsoft.TimeWindow
此篩選提供根據時間範圍啟用功能的功能。 如果只指定了 End
,則會在該時間之前將功能視為開啟。 如果只指定了 Start
,則會在該時間之後的所有時間點將功能視為開啟。
"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
此篩選提供為目標對象啟用功能的功能。 下列目標一節將提供目標設定的深入說明。 篩選參數包含 Audience
物件,描述使用者、群組、排除的使用者/群組,以及應該具有此功能存取權之使用者群的預設百分比。 Groups
區段中所列的每個群組物件也必須指定群組成員應具有存取權的百分比。 如果在 Exclusion
區段中指定了使用者,則無論直接或如果使用者位於排除的群組中,都會停用此功能。 否則,如果直接在 Users
區段中指定使用者,或使用者屬於任何群組推出的內含百分比,或如果使用者落入預設推出百分比,則該使用者就會啟用該功能。
"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"
]
}
}
}
}
]
目標設定
目標是功能管理策略,可讓開發人員逐漸向使用者群推出新功能。 此策略是建立在以一組稱為目標「對象」的使用者為目標的概念之上。 對象由特定使用者、群組、排除的使用者/群組和整個使用者群的指定百分比所組成。 對象中包含的群組可以進一步細分為其成員總數的百分比。
下列步驟示範新 'Beta' 功能的漸進式推出範例:
- 個人使用者 Jeff 和 Alicia 被授與 Beta 的存取權
- 另一位使用者 Mark 要求加入並包含在內。
- Beta 中包含 20% 稱為「Ring1」使用者的群組。
- Beta 中包含的「Ring1」使用者數目高達 100%。
- Beta 中包含 5% 的使用者群。
- 發行百分比高達 100%,且功能已完全推出。
此推出功能的策略會透過內含的 Microsoft.Targeting 功能篩選內建至程式庫。
將使用者設為目標
您可以直接在 is_enabled
呼叫中指定使用者,或者可以使用 TargetingContext
來指定使用者和選擇性群組。
# 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"]))
目標排除
定義對象時,可以從對象中排除使用者和群組。 向一組使用者推出功能時,排除非常有用,但需要從推出中排除少數使用者或群組。 排除是藉由將使用者和群組清單新增至對象的 Exclusion
屬性來定義。
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
在上述範例中,此功能會針對名為 Jeff
和 Alicia
的使用者啟用。 它也會針對名為 Ring0
的群組中的使用者啟用。 不過,如果使用者命名為 Mark
,則不論使用者是否在群組 Ring0
中,都會停用此功能。 排除項目優先於目標篩選的其餘部分。
變體
將新功能新增至應用程式時,總會發生功能有多個不同的建議設計選項的情況。 決定設計的常見解決方案是某種形式的 A/B 測試。 A/B 測試牽涉到將功能的不同版本提供給不同區段的使用者群,並根據使用者互動來選擇版本。 在此程式庫中,此功能是藉由代表具有變體之功能的不同組態來啟用。
變體可讓功能旗標變成不只是簡單的開啟/關閉旗標。 變體代表功能旗標的值,可以是字串、數位、布林值,甚至是組態物件。 宣告變體的功能旗標應該在應使用每個變體的情況下定義,這會在配置變體一節中更詳細地說明。
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
取得變體
針對每個功能,可以使用 FeatureManager
的 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
傳回的變體取決於目前正在評估的使用者,而該資訊會從 TargetingContext
的執行個體中取得。
變體功能旗標宣告
相較於一般功能旗標,變體功能旗標多了兩個屬性:variants
和 allocation
。 variants
屬性是一個數字,其中包含為這項功能定義的變體。 allocation
屬性會定義應該如何為功能配置這些變體。 就像宣告一般功能旗標一樣,您可以在 JSON 檔案中設定變體功能旗標。 以下是變體功能旗標的範例。
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"enabled": true,
"allocation": {
"default_when_enabled": "Small",
"group": [
{
"variant": "Big",
"groups": [
"Ring1"
]
}
]
},
"variants": [
{
"name": "Big"
},
{
"name": "Small"
}
]
}
]
}
}
定義變體
每個變體都有兩個屬性:名稱和組態。 此名稱是用來參考特定變體,而組態是該變體的值。 您可以使用 configuration_value
屬性來設定組態。 configuration_value
是可以是字串、數位、布林值或組態物件的內嵌組態。 如果未指定 configuration_value
,所傳回變體的 Configuration
屬性是 None
。
所有可能變體的清單都會針對 variants
屬性下的每個功能定義。
{
"feature_management": {
"feature_flags": [
{
"id": "MyVariantFeatureFlag",
"variants": [
{
"name": "Big",
"configuration_value": {
"Size": 500
}
},
{
"name": "Small",
"configuration_value": {
"Size": 300
}
}
]
}
]
}
}
配置變體
配置功能變體的程序取決於功能的 allocation
屬性。
"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"
}
]
功能的 allocation
設定具有下列屬性:
屬性 | 說明 |
---|---|
default_when_disabled |
指定當功能被視為停用且要求變體時,應該使用哪一個變體。 |
default_when_enabled |
指定在功能視為已啟用時要求變體,且未將其他變體指派給使用者時,應該使用哪個變體。 |
user |
指定變數和應為其指派該變體的使用者清單。 |
group |
指定變體和群組清單。 如果使用者至少在其中一個群組內,則會指派變體。 |
percentile |
指定變體和使用者計算百分比必須符合才能指派該變體的百分比範圍。 |
seed |
計算 percentile 百分比依據的值。 如果使用相同的 seed 值,特定使用者的百分比計算在所有功能上都會相同。 如果未指定 seed ,則會根據功能名稱建立預設種子。 |
如果未啟用此功能,功能管理員就會將標示為 default_when_disabled
的變體指派給目前使用者,在此案例中為 Small
。
如果啟用此功能,功能管理員將依該順序檢查 user
、group
和 percentile
配置,以指派變體。 在此特定範例中,如果評估的使用者名為 Marsha
,則在名為 Ring1
的群組中,或使用者碰巧落在第 0 到 10 個百分位數之間,則會將指定的變異指派給使用者。 在此案例中,所有指派的使用者都會傳回 Big
變體。 如果這些配置都不相符,則會為使用者指派 default_when_enabled
變體,也就是 Small
。
配置邏輯與 Microsoft.Targeting 功能篩選類似,但目標中有一些參數不在配置中,反之亦然。 目標的結果與配置無關。
使用變體覆寫已啟用狀態
您可以使用變體來覆寫功能旗標的已啟用狀態。 覆寫可讓變體有機會延伸功能旗標的評估。 在具有變體的旗標上呼叫 is_enabled
時,功能管理員會檢查指派至目前使用者的變體是否已設定為覆寫結果。 覆寫會使用選擇性變體屬性 status_override
來完成。 根據預設,這個屬性會設定為 None
,這表示變數不會影響旗標是否被視為已啟用或停用。 將 status_override
設定為 Enabled
可讓變數在選擇時覆寫要啟用的旗標。 將 status_override
設定為 Disabled
可提供相反的功能,因此會在選擇變體時停用旗標。 無法覆寫具有 false
之 enabled
狀態的功能。
如果您使用具有二進位變體的功能旗標,則 status_override
屬性會很有用。 其可讓您繼續在應用程式中使用類似於 is_enabled
的 API,同時受益於變體隨附的新功能,例如,百分位數配置和種子。
{
"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"
}
]
}
在上述範例中,一律會啟用功能。 如果目前使用者位於 10 到 20 的計算百分位數範圍中,則會傳回 On
變體。 否則會傳回 Off
變體,因為 status_override
等於 Disabled
,而功能現在會被視為已停用。
遙測
部署功能旗標變更時,分析其對應用程式的影響通常很重要。 例如,以下是一些可能發生的問題:
- 我的旗標是否如預期般啟用/停用?
- 目標使用者是否如預期般可存取特定功能?
- 特定使用者會看到哪個變體?
這些類型的問題可透過功能旗標評估事件的發出和分析來回答。 此程式庫可以選擇在功能旗標評估期間,透過 OpenTelemetry
,啟用 AzureMonitor
產生追蹤遙測。
啟用遙測
根據預設,功能旗標不會發出遙測。 若要發佈指定功能旗標的遙測,旗標「必須」宣告其已針對遙測發出啟用。
針對 JSON 中定義的功能旗標,啟用會使用 telemetry
屬性來完成。
{
"feature_management": {
"feature_flags": [
{
"id": "MyFeatureFlag",
"enabled": true,
"telemetry": {
"enabled": true
}
}
]
}
}
上述程式碼片段會定義名為 MyFeatureFlag
的功能旗標且已針對遙測啟用。 telemetry
物件的 enabled
屬性會設定為 true
。 enabled
屬性的值必須是 true
才能發佈旗標的遙測。
功能旗標的 telemetry
區段具有下列屬性:
屬性 | 說明 |
---|---|
enabled |
指定是否應該發佈功能旗標的遙測。 |
metadata |
模型化為字典的索引鍵/值組集合,可用來將功能旗標的相關自訂中繼資料附加至評估事件。 |
此外,在建立 FeatureManager
時,必須註冊回呼來處理遙測事件。 每當評估功能旗標並針對該旗標啟用遙測時,就會呼叫此回呼。
feature_manager = FeatureManager(feature_flags, on_feature_evaluated=publish_telemetry)
Application Insights 遙測
功能管理程式庫提供內建的遙測發行者,可將功能旗標評估資料傳送至 Application Insights (英文)。 若要啟用 Application Insights,功能管理程式庫可以透過 pip install FeatureManagement[AzureMonitor]
與 Azure 監視器一起安裝。 此命令會安裝 azure-monitor-events-extension
套件,以使用 OpenTelemetry 來將遙測樣式設定為 Application Insights。
注意
azure-monitor-events-extension
套件只會將遙測新增至 Open Telemetry 管線。 您仍然需要註冊 Application Insights。
from azure.monitor.opentelemetry import configure_azure_monitor
configure_azure_monitor(
connection_string="InstrumentationKey=00000000-0000-0000-0000-000000000000"
)
自訂遙測發佈
由於遙測回呼是一個函式,因此可將其自訂為將遙測發佈至任何所需的目的地。 例如,遙測可以發佈至記錄服務、資料庫或自訂遙測服務。
評估功能旗標並啟用遙測時,功能管理員會使用 EvaluationEvent
參數來呼叫遙測回呼。 EvaluationEvent
包含下列屬性:
標記 | 描述 |
---|---|
feature |
使用的功能旗標。 |
user |
用於目標的使用者識別碼。 |
enabled |
功能旗標是否評估為已啟用。 |
Variant |
指派的變體。 |
VariantAssignmentReason |
指派變體的原因。 |
下一步
若要了解如何在應用程式中使用功能旗標,請繼續進行下列快速入門。
若要了解如何使用功能篩選,請繼續進行下列教學課程。