From 80233a0785a572eae2c9017fcfb0fa35a7696b51 Mon Sep 17 00:00:00 2001 From: Matt Metcalf Date: Thu, 14 Nov 2024 15:31:00 -0800 Subject: [PATCH] 2.0.0 GA --- CHANGELOG.md | 8 +++++++ featuremanagement/_version.py | 2 +- .../azuremonitor/_send_telemetry.py | 23 ++----------------- tests/test_send_telemetry_appinsights.py | 15 ------------ 4 files changed, 11 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb09ca2..8ad7dc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Release History +## 2.0.0 (11/19/2024) + +* GA release of Feature Management supporting Feature Variants. +* GA release of Telemetry support. + * `publish_telemetry` sends: feature name, enabled, telemetry version, reason, variant name, targeting id, and additionally provided metadata. + * `publish_telemetry` can be added as a callback when creating `FeatureManager` with `on_feature_evaluated=publish_telemetry` + & `track_event` a custom event logger that adds the targeting id to the event. + ## 2.0.0b3 (11/14/2024) * Fixes a bug where no allocation reason is set if a user is allocated to exactly 100. diff --git a/featuremanagement/_version.py b/featuremanagement/_version.py index c6590f9..fb4fafa 100644 --- a/featuremanagement/_version.py +++ b/featuremanagement/_version.py @@ -4,4 +4,4 @@ # license information. # ------------------------------------------------------------------------- -VERSION = "2.0.0b3" +VERSION = "2.0.0" diff --git a/featuremanagement/azuremonitor/_send_telemetry.py b/featuremanagement/azuremonitor/_send_telemetry.py index a48628c..fccc94e 100644 --- a/featuremanagement/azuremonitor/_send_telemetry.py +++ b/featuremanagement/azuremonitor/_send_telemetry.py @@ -5,7 +5,7 @@ # -------------------------------------------------------------------------- import logging from typing import Dict, Optional -from .._models import VariantAssignmentReason, EvaluationEvent +from .._models import EvaluationEvent try: from azure.monitor.events.extension import track_event as azure_monitor_track_event # type: ignore @@ -25,7 +25,7 @@ EVENT_NAME = "FeatureEvaluation" -EVALUATION_EVENT_VERSION = "1.1.0" +EVALUATION_EVENT_VERSION = "1.0.0" def track_event(event_name: str, user: str, event_properties: Optional[Dict[str, Optional[str]]] = None) -> None: @@ -75,25 +75,6 @@ def publish_telemetry(evaluation_event: EvaluationEvent) -> None: if variant: event[VARIANT] = variant.name - # VariantAllocationPercentage - allocation_percentage = 0 - if reason == VariantAssignmentReason.DEFAULT_WHEN_ENABLED: - event["VariantAssignmentPercentage"] = str(100) - if feature.allocation: - for allocation in feature.allocation.percentile: - allocation_percentage += allocation.percentile_to - allocation.percentile_from - event["VariantAssignmentPercentage"] = str(100 - allocation_percentage) - elif reason == VariantAssignmentReason.PERCENTILE: - if feature.allocation and feature.allocation.percentile: - for allocation in feature.allocation.percentile: - if variant and allocation.variant == variant.name: - allocation_percentage += allocation.percentile_to - allocation.percentile_from - event["VariantAssignmentPercentage"] = str(allocation_percentage) - - # DefaultWhenEnabled - if feature.allocation and feature.allocation.default_when_enabled: - event["DefaultWhenEnabled"] = feature.allocation.default_when_enabled - if feature.telemetry: for metadata_key, metadata_value in feature.telemetry.metadata.items(): if metadata_key not in event: diff --git a/tests/test_send_telemetry_appinsights.py b/tests/test_send_telemetry_appinsights.py index 073c55f..0260754 100644 --- a/tests/test_send_telemetry_appinsights.py +++ b/tests/test_send_telemetry_appinsights.py @@ -22,7 +22,6 @@ def test_send_telemetry_appinsights(self): "ETag": "cmwBRcIAq1jUyKL3Kj8bvf9jtxBrFg-R-ayExStMC90", "FeatureFlagReference": "fake-store-uri/kv/.appconfig.featureflag/TestFeature", "FeatureFlagId": "fake-feature-flag-id", - "AllocationId": "fake-allocation-id", }, }, } @@ -46,16 +45,12 @@ def test_send_telemetry_appinsights(self): assert mock_track_event.call_args[0][1]["Enabled"] == "True" assert mock_track_event.call_args[0][1]["TargetingId"] == "test_user" assert mock_track_event.call_args[0][1]["Variant"] == "TestVariant" - assert mock_track_event.call_args[0][1]["VariantAssignmentReason"] == "DefaultWhenDisabled" - assert "VariantAssignmentPercentage" not in mock_track_event.call_args[0][1] assert mock_track_event.call_args[0][1]["ETag"] == "cmwBRcIAq1jUyKL3Kj8bvf9jtxBrFg-R-ayExStMC90" assert ( mock_track_event.call_args[0][1]["FeatureFlagReference"] == "fake-store-uri/kv/.appconfig.featureflag/TestFeature" ) assert mock_track_event.call_args[0][1]["FeatureFlagId"] == "fake-feature-flag-id" - assert mock_track_event.call_args[0][1]["AllocationId"] == "fake-allocation-id" - assert "DefaultWhenEnabled" not in mock_track_event.call_args[0][1] def test_send_telemetry_appinsights_no_user(self): feature_flag = FeatureFlag.convert_from_json({"id": "TestFeature"}) @@ -78,8 +73,6 @@ def test_send_telemetry_appinsights_no_user(self): assert "TargetingId" not in mock_track_event.call_args[0][1] assert mock_track_event.call_args[0][1]["Variant"] == "TestVariant" assert mock_track_event.call_args[0][1]["VariantAssignmentReason"] == "DefaultWhenDisabled" - assert "VariantAssignmentPercentage" not in mock_track_event.call_args[0][1] - assert "DefaultWhenEnabled" not in mock_track_event.call_args[0][1] def test_send_telemetry_appinsights_no_variant(self): feature_flag = FeatureFlag.convert_from_json({"id": "TestFeature"}) @@ -143,9 +136,6 @@ def test_send_telemetry_appinsights_default_when_enabled(self): assert mock_track_event.call_args[0][1]["TargetingId"] == "test_user" assert mock_track_event.call_args[0][1]["Variant"] == "big" assert mock_track_event.call_args[0][1]["VariantAssignmentReason"] == "DefaultWhenEnabled" - assert mock_track_event.call_args[0][1]["VariantAssignmentPercentage"] == "25" - assert "DefaultWhenEnabled" in mock_track_event.call_args[0][1] - assert mock_track_event.call_args[0][1]["DefaultWhenEnabled"] == "big" def test_send_telemetry_appinsights_default_when_enabled_no_percentile(self): feature_flag = FeatureFlag.convert_from_json( @@ -176,9 +166,6 @@ def test_send_telemetry_appinsights_default_when_enabled_no_percentile(self): assert mock_track_event.call_args[0][1]["TargetingId"] == "test_user" assert mock_track_event.call_args[0][1]["Variant"] == "big" assert mock_track_event.call_args[0][1]["VariantAssignmentReason"] == "DefaultWhenEnabled" - assert mock_track_event.call_args[0][1]["VariantAssignmentPercentage"] == "100" - assert "DefaultWhenEnabled" in mock_track_event.call_args[0][1] - assert mock_track_event.call_args[0][1]["DefaultWhenEnabled"] == "big" def test_send_telemetry_appinsights_allocation(self): feature_flag = FeatureFlag.convert_from_json( @@ -209,5 +196,3 @@ def test_send_telemetry_appinsights_allocation(self): assert mock_track_event.call_args[0][1]["TargetingId"] == "test_user" assert mock_track_event.call_args[0][1]["Variant"] == "big" assert mock_track_event.call_args[0][1]["VariantAssignmentReason"] == "Percentile" - assert mock_track_event.call_args[0][1]["VariantAssignmentPercentage"] == "25" - assert "DefaultWhenEnabled" not in mock_track_event.call_args[0][1]