From a107c2b548960e5bd5db12d199ebcf8831a5a16e Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Wed, 9 Oct 2024 12:49:52 -0400 Subject: [PATCH 01/17] Revert "Remove Telemetry from main (#37783)" (#37812) This reverts commit a65dfb2c24a90c0b8218bbb968b92ea0abf2a5ff. --- .../provider/_client_manager.py | 2 ++ .../provider/_client_manager_base.py | 23 +++++++++++++++++++ .../provider/aio/_async_client_manager.py | 2 ++ 3 files changed, 27 insertions(+) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager.py index 9e028d695e2c..e9ae3b3b65f7 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager.py @@ -163,6 +163,7 @@ def load_feature_flags( loaded_feature_flags = [] # Needs to be removed unknown keyword argument for list_configuration_settings kwargs.pop("sentinel_keys", None) + endpoint = self._client._impl._config.endpoint # pylint: disable=protected-access filters_used: Dict[str, bool] = {} for select in feature_flag_selectors: feature_flags = self._client.list_configuration_settings( @@ -176,6 +177,7 @@ def load_feature_flags( feature_flag_value = json.loads(feature_flag.value) + self._feature_flag_telemetry(endpoint, feature_flag, feature_flag_value) self._feature_flag_appconfig_telemetry(feature_flag, filters_used) loaded_feature_flags.append(feature_flag_value) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index 38cae3676180..cf7870a4681f 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -20,6 +20,11 @@ PERCENTAGE_FILTER_KEY, TIME_WINDOW_FILTER_KEY, TARGETING_FILTER_KEY, + TELEMETRY_KEY, + METADATA_KEY, + ETAG_KEY, + FEATURE_FLAG_REFERENCE_KEY, + FEATURE_FLAG_ID_KEY, ) FALLBACK_CLIENT_REFRESH_EXPIRED_INTERVAL = 3600 # 1 hour in seconds @@ -40,6 +45,24 @@ def _calculate_feature_id(key, label): encoded_flag = encoded_flag.replace(b"+", b"-").replace(b"/", b"_") return encoded_flag[: encoded_flag.find(b"=")] + def _feature_flag_telemetry( + self, endpoint: str, feature_flag: FeatureFlagConfigurationSetting, feature_flag_value: Dict + ): + if TELEMETRY_KEY in feature_flag_value: + if METADATA_KEY not in feature_flag_value[TELEMETRY_KEY]: + feature_flag_value[TELEMETRY_KEY][METADATA_KEY] = {} + feature_flag_value[TELEMETRY_KEY][METADATA_KEY][ETAG_KEY] = feature_flag.etag + + if not endpoint.endswith("/"): + endpoint += "/" + feature_flag_reference = f"{endpoint}kv/{feature_flag.key}" + if feature_flag.label and not feature_flag.label.isspace(): + feature_flag_reference += f"?label={feature_flag.label}" + feature_flag_value[TELEMETRY_KEY][METADATA_KEY][FEATURE_FLAG_REFERENCE_KEY] = feature_flag_reference + feature_flag_value[TELEMETRY_KEY][METADATA_KEY][FEATURE_FLAG_ID_KEY] = self._calculate_feature_id( + feature_flag.key, feature_flag.label + ) + def _feature_flag_appconfig_telemetry( self, feature_flag: FeatureFlagConfigurationSetting, filters_used: Dict[str, bool] ): diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/aio/_async_client_manager.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/aio/_async_client_manager.py index 8f236695536a..6ba0fa43d1e9 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/aio/_async_client_manager.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/aio/_async_client_manager.py @@ -165,6 +165,7 @@ async def load_feature_flags( loaded_feature_flags = [] # Needs to be removed unknown keyword argument for list_configuration_settings kwargs.pop("sentinel_keys", None) + endpoint = self._client._impl._config.endpoint # pylint: disable=protected-access filters_used: Dict[str, bool] = {} for select in feature_flag_selectors: feature_flags = self._client.list_configuration_settings( @@ -178,6 +179,7 @@ async def load_feature_flags( feature_flag_value = json.loads(feature_flag.value) + self._feature_flag_telemetry(endpoint, feature_flag, feature_flag_value) self._feature_flag_appconfig_telemetry(feature_flag, filters_used) loaded_feature_flags.append(feature_flag_value) From be1b8fd4443cfb553f925d34a2ec6166631034cd Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Fri, 11 Oct 2024 13:56:26 -0400 Subject: [PATCH 02/17] Allocation Id (#37840) * Adding Telemetry * Telemetry Support * fixing formatting * Update _azureappconfigurationprovider.py * Update _azureappconfigurationproviderasync.py * formatting * changing doc style due to pylint-next * fixing kwargs docs * Formatting * Review comments * Changed label checking. * black format changes * pylint * Update sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_azureappconfigurationprovider.py Co-authored-by: Avani Gupta * added space checks * Update conftest.py * moved telemetry to client wrapper * fixing format * updating after merge * fixing black issue * removing unused imports * AllocationId * Update CODEOWNERS * Update CODEOWNERS * fixing issues * Update _client_manager_base.py * Fixing configuration value empty in calc * fixing pylint * Update _constants.py * review comments * fixing allocation check * format fix --------- Co-authored-by: Avani Gupta --- .github/CODEOWNERS | 2 +- .../provider/_client_manager_base.py | 99 +++++++++++++++++-- .../appconfiguration/provider/_constants.py | 4 +- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 24e6ae35ddbb..cd04f9662e23 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -87,7 +87,7 @@ # ServiceLabel: %App Configuration Provider # PRLabel: %App Configuration Provider -/sdk/appconfiguration/azure-appconfiguration-provider/ @mametcal @albertofori @avanigupta @mrm9084 +/sdk/appconfiguration/azure-appconfiguration-provider/ @albertofori @avanigupta @mrm9084 @rossgrambo # ServiceLabel: %Attestation # PRLabel: %Attestation diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index cf7870a4681f..d38b518a64db 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -3,12 +3,13 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # ------------------------------------------------------------------------- +import json import time import random import hashlib import base64 from dataclasses import dataclass -from typing import Dict, List +from typing import Dict, List, Optional, Mapping, Any from azure.appconfiguration import ( # type:ignore # pylint:disable=no-name-in-module FeatureFlagConfigurationSetting, ) @@ -25,24 +26,104 @@ ETAG_KEY, FEATURE_FLAG_REFERENCE_KEY, FEATURE_FLAG_ID_KEY, + ALLOCATION_ID_KEY, ) FALLBACK_CLIENT_REFRESH_EXPIRED_INTERVAL = 3600 # 1 hour in seconds MINIMAL_CLIENT_REFRESH_INTERVAL = 30 # 30 seconds +JSON = Mapping[str, Any] + @dataclass class _ConfigurationClientWrapperBase: endpoint: str + @staticmethod + def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str]: + """ + Generates an allocation ID for the specified feature. + seed=123abc\ndefault_when_enabled=Control\npercentiles=0,Control,20;20,Test,100\nvariants=Control,standard;Test,special # pylint:disable=line-too-long + + :param Dict[str, JSON] feature_flag_value: The feature to generate an allocation ID for. + :rtype: str + :return: The allocation ID. + """ + + allocation_id = "" + allocated_variants = [] + + allocation: Optional[JSON] = feature_flag_value.get("allocation") + + if allocation: + # Seed + allocation_id = f"seed={allocation.get('seed', '')}" + + # DefaultWhenEnabled + if "default_when_enabled" in allocation: + allocated_variants.append(allocation.get("default_when_enabled")) + + allocation_id += f"\ndefault_when_enabled={allocation.get('default_when_enabled', '')}" + + # Percentile + allocation_id += "\npercentiles=" + + percentile = allocation.get("percentile") + + if percentile: + percentile_allocations = sorted( + (x for x in percentile if x.get("from") != x.get("to")), + key=lambda x: x.get("from"), + ) + + for percentile_allocation in percentile_allocations: + if "variant" in percentile_allocation: + allocated_variants.append(percentile_allocation.get("variant")) + + allocation_id += ";".join( + f"{pa.get('from')}," f"{base64.b64encode(pa.get('variant').encode()).decode()}," f"{pa.get('to')}" + for pa in percentile_allocations + ) + else: + allocation_id = "seed=\ndefault_when_enabled=\npercentiles=" + + if not allocated_variants and (not allocation or not allocation.get("seed")): + return None + + # Variants + allocation_id += "\nvariants=" + + variants_value = feature_flag_value.get("variants") + if variants_value and (isinstance(variants_value, list) or all(isinstance(v, dict) for v in variants_value)): + if allocated_variants: + if isinstance(variants_value, list) and all(isinstance(v, dict) for v in variants_value): + sorted_variants: List[Dict[str, Any]] = sorted( + (v for v in variants_value if v.get("name") in allocated_variants), + key=lambda v: v.get("name"), + ) + + for v in sorted_variants: + allocation_id += f"{base64.b64encode(v.get('name', '').encode()).decode()}," + if "configuration_value" in v: + allocation_id += f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'))}" + allocation_id += ";" + allocation_id = allocation_id[:-1] + + # Create a sha256 hash of the allocation_id + hash_object = hashlib.sha256(allocation_id.encode()) + hash_digest = hash_object.digest() + + # Encode the first 15 bytes in base64 url + allocation_id_hash = base64.urlsafe_b64encode(hash_digest[:15]).decode() + return allocation_id_hash + @staticmethod def _calculate_feature_id(key, label): basic_value = f"{key}\n" if label and not label.isspace(): basic_value += f"{label}" feature_flag_id_hash_bytes = hashlib.sha256(basic_value.encode()).digest() - encoded_flag = base64.b64encode(feature_flag_id_hash_bytes) - encoded_flag = encoded_flag.replace(b"+", b"-").replace(b"/", b"_") + encoded_flag = base64.urlsafe_b64encode(feature_flag_id_hash_bytes) return encoded_flag[: encoded_flag.find(b"=")] def _feature_flag_telemetry( @@ -58,10 +139,14 @@ def _feature_flag_telemetry( feature_flag_reference = f"{endpoint}kv/{feature_flag.key}" if feature_flag.label and not feature_flag.label.isspace(): feature_flag_reference += f"?label={feature_flag.label}" - feature_flag_value[TELEMETRY_KEY][METADATA_KEY][FEATURE_FLAG_REFERENCE_KEY] = feature_flag_reference - feature_flag_value[TELEMETRY_KEY][METADATA_KEY][FEATURE_FLAG_ID_KEY] = self._calculate_feature_id( - feature_flag.key, feature_flag.label - ) + if feature_flag_value[TELEMETRY_KEY].get("enabled"): + feature_flag_value[TELEMETRY_KEY][METADATA_KEY][FEATURE_FLAG_REFERENCE_KEY] = feature_flag_reference + feature_flag_value[TELEMETRY_KEY][METADATA_KEY][FEATURE_FLAG_ID_KEY] = self._calculate_feature_id( + feature_flag.key, feature_flag.label + ) + allocation_id = self._generate_allocation_id(feature_flag_value) + if allocation_id: + feature_flag_value[TELEMETRY_KEY][METADATA_KEY][ALLOCATION_ID_KEY] = allocation_id def _feature_flag_appconfig_telemetry( self, feature_flag: FeatureFlagConfigurationSetting, filters_used: Dict[str, bool] diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_constants.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_constants.py index 4e2c0db60cf4..fb9c61e83847 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_constants.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_constants.py @@ -19,10 +19,12 @@ TELEMETRY_KEY = "telemetry" METADATA_KEY = "metadata" -ETAG_KEY = "ETag" +ALLOCATION_ID_KEY = "AllocationId" +ETAG_KEY = "ETag" FEATURE_FLAG_REFERENCE_KEY = "FeatureFlagReference" FEATURE_FLAG_ID_KEY = "FeatureFlagId" + PERCENTAGE_FILTER_NAMES = ["Percentage", "PercentageFilter", "Microsoft.Percentage", "Microsoft.PercentageFilter"] TIME_WINDOW_FILTER_NAMES = ["TimeWindow", "TimeWindowFilter", "Microsoft.TimeWindow", "Microsoft.TimeWindowFilter"] TARGETING_FILTER_NAMES = ["Targeting", "TargetingFilter", "Microsoft.Targeting", "Microsoft.TargetingFilter"] From dad8a4dc52fe10900463f0457ea269f55bf9a8ab Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Fri, 11 Oct 2024 16:35:48 -0400 Subject: [PATCH 03/17] Python Provider 2.0.0b2 Changelog update (#37860) * Update CHANGELOG.md * Update CHANGELOG.md --- .../azure-appconfiguration-provider/CHANGELOG.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index 1126761c4a42..c555e7c99de0 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,10 +1,17 @@ # Release History -## 2.0.0b2 (2024-09-12) +## 2.0.0b2 (2024-10-11) + +### Feature Added + +* Added AllocationId to the feature flag telemetry metadata when the feature flag has telemetry enabled. ### Bugs Fixed -* Fixing ETag to be "ETag" instead of "etag" in feature flag telemetry. +* Fixed a number of cases where snake case was used instead of pascal case for feature flag telemetry. + * etag -> ETag + * feature_flag_reference -> FeatureFlagReference + * feature_flag_id -> FeatureFlagId ## 2.0.0b1 (2024-09-11) From 5c0ca902beec87d0252e2aee66923047cee9af84 Mon Sep 17 00:00:00 2001 From: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:58:50 -0700 Subject: [PATCH 04/17] Increment package version after release of azure-appconfiguration-provider (#37877) --- .../azure-appconfiguration-provider/CHANGELOG.md | 10 ++++++++++ .../azure/appconfiguration/provider/_version.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index c555e7c99de0..d49e4ac9f539 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 2.0.0b3 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 2.0.0b2 (2024-10-11) ### Feature Added diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py index 99e8b1d451ca..c6590f9fb8b1 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py @@ -4,4 +4,4 @@ # license information. # ------------------------------------------------------------------------- -VERSION = "2.0.0b2" +VERSION = "2.0.0b3" From 561dc06f09d5f13eba39aa82613b216fe8800ade Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Tue, 22 Oct 2024 10:10:06 -0700 Subject: [PATCH 05/17] Update _client_manager_base.py (#38019) --- .../provider/_client_manager_base.py | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index d38b518a64db..32d4c7aaf771 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -55,37 +55,37 @@ def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str allocation: Optional[JSON] = feature_flag_value.get("allocation") - if allocation: - # Seed - allocation_id = f"seed={allocation.get('seed', '')}" + if not allocation: + return None - # DefaultWhenEnabled - if "default_when_enabled" in allocation: - allocated_variants.append(allocation.get("default_when_enabled")) + # Seed + allocation_id = f"seed={allocation.get('seed', '')}" - allocation_id += f"\ndefault_when_enabled={allocation.get('default_when_enabled', '')}" + # DefaultWhenEnabled + if "default_when_enabled" in allocation: + allocated_variants.append(allocation.get("default_when_enabled")) - # Percentile - allocation_id += "\npercentiles=" + allocation_id += f"\ndefault_when_enabled={allocation.get('default_when_enabled', '')}" - percentile = allocation.get("percentile") + # Percentile + allocation_id += "\npercentiles=" - if percentile: - percentile_allocations = sorted( - (x for x in percentile if x.get("from") != x.get("to")), - key=lambda x: x.get("from"), - ) + percentile = allocation.get("percentile") - for percentile_allocation in percentile_allocations: - if "variant" in percentile_allocation: - allocated_variants.append(percentile_allocation.get("variant")) + if percentile: + percentile_allocations = sorted( + (x for x in percentile if x.get("from") != x.get("to")), + key=lambda x: x.get("from"), + ) - allocation_id += ";".join( - f"{pa.get('from')}," f"{base64.b64encode(pa.get('variant').encode()).decode()}," f"{pa.get('to')}" - for pa in percentile_allocations - ) - else: - allocation_id = "seed=\ndefault_when_enabled=\npercentiles=" + for percentile_allocation in percentile_allocations: + if "variant" in percentile_allocation: + allocated_variants.append(percentile_allocation.get("variant")) + + allocation_id += ";".join( + f"{pa.get('from')}," f"{base64.b64encode(pa.get('variant').encode()).decode()}," f"{pa.get('to')}" + for pa in percentile_allocations + ) if not allocated_variants and (not allocation or not allocation.get("seed")): return None @@ -95,18 +95,22 @@ def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str variants_value = feature_flag_value.get("variants") if variants_value and (isinstance(variants_value, list) or all(isinstance(v, dict) for v in variants_value)): - if allocated_variants: - if isinstance(variants_value, list) and all(isinstance(v, dict) for v in variants_value): - sorted_variants: List[Dict[str, Any]] = sorted( - (v for v in variants_value if v.get("name") in allocated_variants), - key=lambda v: v.get("name"), - ) - - for v in sorted_variants: - allocation_id += f"{base64.b64encode(v.get('name', '').encode()).decode()}," - if "configuration_value" in v: - allocation_id += f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'))}" - allocation_id += ";" + if ( + allocated_variants + and isinstance(variants_value, list) + and all(isinstance(v, dict) for v in variants_value) + ): + sorted_variants: List[Dict[str, Any]] = sorted( + (v for v in variants_value if v.get("name") in allocated_variants), + key=lambda v: v.get("name"), + ) + + for v in sorted_variants: + allocation_id += f"{base64.b64encode(v.get('name', '').encode()).decode()}," + if "configuration_value" in v: + allocation_id += f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'))}" + allocation_id += ";" + if sorted_variants: allocation_id = allocation_id[:-1] # Create a sha256 hash of the allocation_id From c973431dfa6ddab582eb9f5de3aed87fdfbb7821 Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Wed, 23 Oct 2024 16:32:24 -0700 Subject: [PATCH 06/17] App Config Allocation Id Update (#38065) * updated calc to sort keys * Update CHANGELOG.md --- .../azure-appconfiguration-provider/CHANGELOG.md | 2 ++ .../azure/appconfiguration/provider/_client_manager_base.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index d49e4ac9f539..a4c8df026bbf 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -6,6 +6,8 @@ ### Breaking Changes +* Allocation Id value changed so other providers can match the value. + ### Bugs Fixed ### Other Changes diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index 32d4c7aaf771..7ad64a1a21bf 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -108,7 +108,9 @@ def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str for v in sorted_variants: allocation_id += f"{base64.b64encode(v.get('name', '').encode()).decode()}," if "configuration_value" in v: - allocation_id += f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'))}" + allocation_id += ( + f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'), sort_keys=True)}," + ) allocation_id += ";" if sorted_variants: allocation_id = allocation_id[:-1] From e994d82fbe11682b16666ecbfe6ad2373a94762d Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Thu, 31 Oct 2024 12:24:32 -0700 Subject: [PATCH 07/17] Allocation id update (#38242) * updated calc to sort keys * Update CHANGELOG.md * Update _client_manager_base.py --- .../azure/appconfiguration/provider/_client_manager_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index 7ad64a1a21bf..cb5bd5de89f2 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -109,7 +109,7 @@ def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str allocation_id += f"{base64.b64encode(v.get('name', '').encode()).decode()}," if "configuration_value" in v: allocation_id += ( - f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'), sort_keys=True)}," + f"{json.dumps(v.get('configuration_value', ''), separators=(',', ':'), sort_keys=True)}" ) allocation_id += ";" if sorted_variants: From 68b9623c910bb344323c3087a8dfd313f8c8181d Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Wed, 13 Nov 2024 13:05:14 -0800 Subject: [PATCH 08/17] Update CHANGELOG.md (#38521) --- .../azure-appconfiguration-provider/CHANGELOG.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index a4c8df026bbf..3983bdb8e63c 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,17 +1,11 @@ # Release History -## 2.0.0b3 (Unreleased) - -### Features Added +## 2.0.0b3 (2024-11-13) ### Breaking Changes * Allocation Id value changed so other providers can match the value. -### Bugs Fixed - -### Other Changes - ## 2.0.0b2 (2024-10-11) ### Feature Added From 0f578588022b0daa4042da23d43987240b15a9af Mon Sep 17 00:00:00 2001 From: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:03:45 -0800 Subject: [PATCH 09/17] Increment package version after release of azure-appconfiguration-provider (#38553) --- .../azure-appconfiguration-provider/CHANGELOG.md | 10 ++++++++++ .../azure/appconfiguration/provider/_version.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index 3983bdb8e63c..2d48c7dd6cd6 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 2.0.0b4 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 2.0.0b3 (2024-11-13) ### Breaking Changes diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py index c6590f9fb8b1..783d6dcfe961 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py @@ -4,4 +4,4 @@ # license information. # ------------------------------------------------------------------------- -VERSION = "2.0.0b3" +VERSION = "2.0.0b4" From 68a5efe9e06505217cfb7908cf26f5e9eb1c8779 Mon Sep 17 00:00:00 2001 From: Matt Metcalf Date: Tue, 8 Apr 2025 14:25:15 -0700 Subject: [PATCH 10/17] fixing imports --- .../azure/appconfiguration/provider/_client_manager_base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index 5be3567cdc18..3887d60992c0 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -4,12 +4,11 @@ # license information. # ------------------------------------------------------------------------- import json -import time import random import hashlib import base64 from dataclasses import dataclass -from typing import Dict, List, Optional, Mapping, Any, Optional +from typing import Dict, List, Optional, Mapping, Any from azure.appconfiguration import ( # type:ignore # pylint:disable=no-name-in-module FeatureFlagConfigurationSetting, ) From b299b70b166d0646fc3c32bf8f37cc42e969d468 Mon Sep 17 00:00:00 2001 From: Matt Metcalf Date: Thu, 10 Apr 2025 10:16:48 -0700 Subject: [PATCH 11/17] Updating Version and Changelog --- .../azure-appconfiguration-provider/CHANGELOG.md | 7 +++++++ .../azure/appconfiguration/provider/_version.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index 719372ccf298..a6a3244143eb 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,5 +1,12 @@ # Release History +## 2.1.0b1 (2025-04-10) + +### Bugs Fixed + +* Updates the feature flag telemetry to use the provided endpoint instead of the endpoint of the store the feature flag was loaded from. +* Removes Feature Id from feature flag telemetry. + ## 2.0.1 (2025-03-07) ### Bugs Fixed diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py index 1e7f42dc01e9..a4dad577a7b6 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py @@ -4,4 +4,4 @@ # license information. # ------------------------------------------------------------------------- -VERSION = "2.0.1" +VERSION = "2.1.0b1" From ffffa36331bcb4f78c314235b49c09378363c28d Mon Sep 17 00:00:00 2001 From: Matt Metcalf Date: Thu, 10 Apr 2025 11:49:21 -0700 Subject: [PATCH 12/17] Update _client_manager_base.py --- .../azure/appconfiguration/provider/_client_manager_base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index 2b3cf0ad87a6..a11fcbf3f65b 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -5,6 +5,8 @@ # ------------------------------------------------------------------------- import json import random +import base64 +import hashlib from dataclasses import dataclass from typing import Dict, List, Optional, Mapping, Any from azure.appconfiguration import ( # type:ignore # pylint:disable=no-name-in-module From ecb55a9d092d2ead4480bedfee0f424f645ab176 Mon Sep 17 00:00:00 2001 From: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Date: Thu, 10 Apr 2025 15:31:26 -0700 Subject: [PATCH 13/17] Increment package version after release of azure-appconfiguration-provider (#40470) --- .../azure-appconfiguration-provider/CHANGELOG.md | 10 ++++++++++ .../azure/appconfiguration/provider/_version.py | 2 +- .../azure-appconfiguration-provider/setup.py | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index a6a3244143eb..bdbbfcd65632 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,5 +1,15 @@ # Release History +## 2.1.0b2 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 2.1.0b1 (2025-04-10) ### Bugs Fixed diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py index a4dad577a7b6..00ccd1bb840a 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py @@ -4,4 +4,4 @@ # license information. # ------------------------------------------------------------------------- -VERSION = "2.1.0b1" +VERSION = "2.1.0b2" diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/setup.py b/sdk/appconfiguration/azure-appconfiguration-provider/setup.py index 53e11fe5b3e5..58530800f3cd 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/setup.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/setup.py @@ -57,7 +57,7 @@ url="https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/appconfiguration/azure-appconfiguration-provider", keywords="azure, azure sdk", classifiers=[ - "Development Status :: 5 - Production/Stable", + "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", From b99f07021b22e717b1a5f53ad095401edcdad456 Mon Sep 17 00:00:00 2001 From: Matt Metcalf Date: Fri, 25 Apr 2025 14:50:35 -0700 Subject: [PATCH 14/17] Updating for release --- .../azure-appconfiguration-provider/CHANGELOG.md | 8 ++------ .../appconfiguration/provider/_client_manager_base.py | 3 +-- .../azure/appconfiguration/provider/_version.py | 2 +- .../azure-appconfiguration-provider/setup.py | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index e1d4e961b719..b89897d63ee1 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -1,14 +1,10 @@ # Release History -## 2.0.3 (Unreleased) +## 2.1.0 (2025-04-28) ### Features Added -### Breaking Changes - -### Bugs Fixed - -### Other Changes +* Added AllocationId to the feature flag telemetry metadata when the feature flag has telemetry enabled. ## 2.1.0b1 (2025-04-10) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index a11fcbf3f65b..79dc43a8445d 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -118,8 +118,7 @@ def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str hash_digest = hash_object.digest() # Encode the first 15 bytes in base64 url - allocation_id_hash = base64.urlsafe_b64encode(hash_digest[:15]).decode() - return allocation_id_hash + return base64.urlsafe_b64encode(hash_digest[:15]).decode() def _feature_flag_telemetry( self, endpoint: str, feature_flag: FeatureFlagConfigurationSetting, feature_flag_value: Dict diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py index 920a4130e7ae..bade305c8529 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_version.py @@ -4,4 +4,4 @@ # license information. # ------------------------------------------------------------------------- -VERSION = "2.0.3" +VERSION = "2.1.0" diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/setup.py b/sdk/appconfiguration/azure-appconfiguration-provider/setup.py index 58530800f3cd..53e11fe5b3e5 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/setup.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/setup.py @@ -57,7 +57,7 @@ url="https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/appconfiguration/azure-appconfiguration-provider", keywords="azure, azure sdk", classifiers=[ - "Development Status :: 4 - Beta", + "Development Status :: 5 - Production/Stable", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", From df544d1416843fab8970cbfb42796796cfee6338 Mon Sep 17 00:00:00 2001 From: Matt Metcalf Date: Fri, 25 Apr 2025 14:51:53 -0700 Subject: [PATCH 15/17] Update CHANGELOG.md --- .../azure-appconfiguration-provider/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index b89897d63ee1..6ed7814fa86a 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -18,6 +18,7 @@ ### Other Changes * Updates telemetry for JSON usage. + ## 2.0.1 (2025-03-07) ### Bugs Fixed From 93351509fe3fee4918a2caa396d2dd2c135158e8 Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Fri, 25 Apr 2025 15:07:56 -0700 Subject: [PATCH 16/17] Update sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md Co-authored-by: Ross Grambo --- .../azure-appconfiguration-provider/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md index 6ed7814fa86a..80d60449d9b8 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md +++ b/sdk/appconfiguration/azure-appconfiguration-provider/CHANGELOG.md @@ -11,7 +11,7 @@ ### Bugs Fixed * Updates the feature flag telemetry to use the provided endpoint instead of the endpoint of the store the feature flag was loaded from. -* Removes Feature Id from feature flag telemetry. +* Removes FeatureFlagId from feature flag telemetry. ## 2.0.2 (2025-04-17) From 63c0d8b42dddccafe4feae8d0dae4300f0a1ac43 Mon Sep 17 00:00:00 2001 From: Matthew Metcalf Date: Fri, 25 Apr 2025 15:09:07 -0700 Subject: [PATCH 17/17] Update sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../azure/appconfiguration/provider/_client_manager_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py index 79dc43a8445d..d80355e589a8 100644 --- a/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py +++ b/sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_client_manager_base.py @@ -85,7 +85,7 @@ def _generate_allocation_id(feature_flag_value: Dict[str, JSON]) -> Optional[str for pa in percentile_allocations ) - if not allocated_variants and (not allocation or not allocation.get("seed")): + if not allocated_variants and not allocation.get("seed"): return None # Variants