From 03be00689a4a702d99dcb70dcc4d5ec3a3405e57 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Fri, 31 May 2024 20:22:16 +0800 Subject: [PATCH 1/7] fix xUnit1031 warning (#557) --- .../FailoverTests.cs | 10 +-- .../FeatureManagementTests.cs | 26 ++++---- .../KeyVaultReferenceTests.cs | 20 +++--- .../LoggingTests.cs | 46 ++++++------- tests/Tests.AzureAppConfiguration/MapTests.cs | 24 +++---- .../PushRefreshTests.cs | 8 +-- .../RefreshTests.cs | 65 ++++++++++--------- 7 files changed, 100 insertions(+), 99 deletions(-) diff --git a/tests/Tests.AzureAppConfiguration/FailoverTests.cs b/tests/Tests.AzureAppConfiguration/FailoverTests.cs index d302e407..e9a7a12a 100644 --- a/tests/Tests.AzureAppConfiguration/FailoverTests.cs +++ b/tests/Tests.AzureAppConfiguration/FailoverTests.cs @@ -23,7 +23,7 @@ public class FailOverTests contentType: "text"); [Fact] - public void FailOverTests_ReturnsAllClientsIfAllBackedOff() + public async Task FailOverTests_ReturnsAllClientsIfAllBackedOff() { // Arrange IConfigurationRefresher refresher = null; @@ -85,7 +85,7 @@ public void FailOverTests_ReturnsAllClientsIfAllBackedOff() // Assert the inner request failed exceptions Assert.True((exception.InnerException as AggregateException)?.InnerExceptions?.All(e => e is RequestFailedException) ?? false); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // The client manager should have called RefreshClients when all clients were backed off Assert.Equal(1, configClientManager.RefreshClientsCalled); @@ -144,7 +144,7 @@ public void FailOverTests_PropagatesNonFailOverableExceptions() } [Fact] - public void FailOverTests_BackoffStateIsUpdatedOnSuccessfulRequest() + public async Task FailOverTests_BackoffStateIsUpdatedOnSuccessfulRequest() { // Arrange IConfigurationRefresher refresher = null; @@ -199,7 +199,7 @@ public void FailOverTests_BackoffStateIsUpdatedOnSuccessfulRequest() refresher = options.GetRefresher(); }).Build(); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // The first client should not have been called during refresh mockClient1.Verify(mc => mc.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(0)); @@ -211,7 +211,7 @@ public void FailOverTests_BackoffStateIsUpdatedOnSuccessfulRequest() // Wait for client 1 backoff to end Thread.Sleep(2500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // The first client should have been called now with refresh after the backoff time ends mockClient1.Verify(mc => mc.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(1)); diff --git a/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs b/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs index 99348464..809187fd 100644 --- a/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs +++ b/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs @@ -452,7 +452,7 @@ public void UsesFeatureFlags() } [Fact] - public void WatchesFeatureFlags() + public async Task WatchesFeatureFlags() { var featureFlags = new List { _kv }; @@ -513,7 +513,7 @@ public void WatchesFeatureFlags() // Sleep to let the cache expire Thread.Sleep(cacheExpirationTimeSpan); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("Browser", config["FeatureManagement:Beta:EnabledFor:0:Name"]); Assert.Equal("Chrome", config["FeatureManagement:Beta:EnabledFor:0:Parameters:AllowedBrowsers:0"]); @@ -523,7 +523,7 @@ public void WatchesFeatureFlags() [Fact] - public void SkipRefreshIfCacheNotExpired() + public async Task SkipRefreshIfCacheNotExpired() { var featureFlags = new List { _kv }; @@ -581,7 +581,7 @@ public void SkipRefreshIfCacheNotExpired() featureFlags.Add(_kv2); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("Browser", config["FeatureManagement:Beta:EnabledFor:0:Name"]); Assert.Equal("Firefox", config["FeatureManagement:Beta:EnabledFor:0:Parameters:AllowedBrowsers:0"]); @@ -618,7 +618,7 @@ public void PreservesDefaultQuery() } [Fact] - public void QueriesFeatureFlags() + public async Task QueriesFeatureFlags() { var mockTransport = new MockTransport(req => { @@ -646,7 +646,7 @@ public void QueriesFeatureFlags() } [Fact] - public void UsesEtagForFeatureFlagRefresh() + public async Task UsesEtagForFeatureFlagRefresh() { var mockClient = new Mock(MockBehavior.Strict); mockClient.Setup(c => c.GetConfigurationSettingsAsync(It.IsAny(), It.IsAny())) @@ -667,7 +667,7 @@ public void UsesEtagForFeatureFlagRefresh() // Sleep to let the cache expire Thread.Sleep(cacheExpirationTimeSpan); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); mockClient.Verify(c => c.GetConfigurationSettingsAsync(It.IsAny(), It.IsAny()), Times.Exactly(3)); } @@ -1025,7 +1025,7 @@ public void MultipleCallsToUseFeatureFlagsWithSelectAndLabel() } [Fact] - public void DifferentCacheExpirationsForMultipleFeatureFlagRegistrations() + public async Task DifferentCacheExpirationsForMultipleFeatureFlagRegistrations() { var mockResponse = new Mock(); var mockClient = new Mock(MockBehavior.Strict); @@ -1111,7 +1111,7 @@ public void DifferentCacheExpirationsForMultipleFeatureFlagRegistrations() // Sleep to let the cache for feature flag with label1 expire Thread.Sleep(cacheExpiration1); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("Browser", config["FeatureManagement:App1_Feature1:EnabledFor:0:Name"]); Assert.Equal("Chrome", config["FeatureManagement:App1_Feature1:EnabledFor:0:Parameters:AllowedBrowsers:0"]); @@ -1125,7 +1125,7 @@ public void DifferentCacheExpirationsForMultipleFeatureFlagRegistrations() } [Fact] - public void OverwrittenCacheExpirationForSameFeatureFlagRegistrations() + public async Task OverwrittenCacheExpirationForSameFeatureFlagRegistrations() { var mockResponse = new Mock(); var mockClient = new Mock(MockBehavior.Strict); @@ -1188,7 +1188,7 @@ public void OverwrittenCacheExpirationForSameFeatureFlagRegistrations() eTag: new ETag("c3c231fd-39a0-4cb6-3237-4614474b92c1" + "f")); Thread.Sleep(cacheExpiration1); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // The cache expiration time for feature flags was overwritten by second call to UseFeatureFlags. // Sleeping for cacheExpiration1 time should not update feature flags. @@ -1200,7 +1200,7 @@ public void OverwrittenCacheExpirationForSameFeatureFlagRegistrations() } [Fact] - public void SelectAndRefreshSingleFeatureFlag() + public async Task SelectAndRefreshSingleFeatureFlag() { var mockResponse = new Mock(); var mockClient = new Mock(MockBehavior.Strict); @@ -1258,7 +1258,7 @@ public void SelectAndRefreshSingleFeatureFlag() // Sleep to let the cache for feature flag with label1 expire Thread.Sleep(cacheExpiration); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("Browser", config["FeatureManagement:Feature1:EnabledFor:0:Name"]); Assert.Equal("Chrome", config["FeatureManagement:Feature1:EnabledFor:0:Parameters:AllowedBrowsers:0"]); diff --git a/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs b/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs index 88c15ffb..9d4ce1e5 100644 --- a/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs +++ b/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs @@ -683,7 +683,7 @@ public void ThrowsWhenSecretRefreshIntervalIsTooShort() } [Fact] - public void SecretIsReturnedFromCacheIfSecretCacheHasNotExpired() + public async Task SecretIsReturnedFromCacheIfSecretCacheHasNotExpired() { IConfigurationRefresher refresher = null; TimeSpan cacheExpirationTime = TimeSpan.FromSeconds(1); @@ -745,7 +745,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Update sentinel key-value sentinelKv.Value = "Value2"; Thread.Sleep(cacheExpirationTime); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("Value2", config["Sentinel"]); Assert.Equal(_secretValue, config[_kv.Key]); @@ -756,7 +756,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o } [Fact] - public void CachedSecretIsInvalidatedWhenRefreshAllIsTrue() + public async Task CachedSecretIsInvalidatedWhenRefreshAllIsTrue() { IConfigurationRefresher refresher = null; TimeSpan cacheExpirationTime = TimeSpan.FromSeconds(1); @@ -817,7 +817,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Update sentinel key-value to trigger refresh operation sentinelKv.Value = "Value2"; Thread.Sleep(cacheExpirationTime); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("Value2", config["Sentinel"]); Assert.Equal(_secretValue, config[_kv.Key]); @@ -828,7 +828,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o } [Fact] - public void SecretIsReloadedFromKeyVaultWhenCacheExpires() + public async Task SecretIsReloadedFromKeyVaultWhenCacheExpires() { IConfigurationRefresher refresher = null; TimeSpan cacheExpirationTime = TimeSpan.FromSeconds(1); @@ -862,7 +862,7 @@ public void SecretIsReloadedFromKeyVaultWhenCacheExpires() // Sleep to let the secret cache expire Thread.Sleep(cacheExpirationTime); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal(_secretValue, config[_kv.Key]); @@ -871,7 +871,7 @@ public void SecretIsReloadedFromKeyVaultWhenCacheExpires() } [Fact] - public void SecretsWithDefaultRefreshInterval() + public async Task SecretsWithDefaultRefreshInterval() { IConfigurationRefresher refresher = null; TimeSpan shortCacheExpirationTime = TimeSpan.FromSeconds(1); @@ -906,7 +906,7 @@ public void SecretsWithDefaultRefreshInterval() // Sleep to let the secret cache expire for both secrets Thread.Sleep(shortCacheExpirationTime); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal(_secretValue, config["TK1"]); Assert.Equal(_secretValue, config["TK2"]); @@ -916,7 +916,7 @@ public void SecretsWithDefaultRefreshInterval() } [Fact] - public void SecretsWithDifferentRefreshIntervals() + public async Task SecretsWithDifferentRefreshIntervals() { IConfigurationRefresher refresher = null; TimeSpan shortCacheExpirationTime = TimeSpan.FromSeconds(1); @@ -953,7 +953,7 @@ public void SecretsWithDifferentRefreshIntervals() // Sleep to let the secret cache expire for one secret Thread.Sleep(shortCacheExpirationTime); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal(_secretValue, config["TK1"]); Assert.Equal(_secretValue, config["TK2"]); diff --git a/tests/Tests.AzureAppConfiguration/LoggingTests.cs b/tests/Tests.AzureAppConfiguration/LoggingTests.cs index 96aa5933..489bb78e 100644 --- a/tests/Tests.AzureAppConfiguration/LoggingTests.cs +++ b/tests/Tests.AzureAppConfiguration/LoggingTests.cs @@ -55,7 +55,7 @@ public class LoggingTests TimeSpan CacheExpirationTime = TimeSpan.FromSeconds(1); [Fact] - public void ValidateExceptionLoggedDuringRefresh() + public async Task ValidateExceptionLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -92,14 +92,14 @@ public void ValidateExceptionLoggedDuringRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.NotEqual("newValue1", config["TestKey1"]); Assert.Contains(LoggingConstants.RefreshFailedError, warningInvocation); } [Fact] - public void ValidateUnauthorizedExceptionLoggedDuringRefresh() + public async Task ValidateUnauthorizedExceptionLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -134,14 +134,14 @@ public void ValidateUnauthorizedExceptionLoggedDuringRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.NotEqual("newValue1", config["TestKey1"]); Assert.Contains(LoggingConstants.RefreshFailedDueToAuthenticationError, warningInvocation); } [Fact] - public void ValidateInvalidOperationExceptionLoggedDuringRefresh() + public async Task ValidateInvalidOperationExceptionLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -176,14 +176,14 @@ public void ValidateInvalidOperationExceptionLoggedDuringRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.NotEqual("newValue1", config["TestKey1"]); Assert.Contains(LoggingConstants.RefreshFailedError, warningInvocation); } [Fact] - public void ValidateKeyVaultExceptionLoggedDuringRefresh() + public async Task ValidateKeyVaultExceptionLoggedDuringRefresh() { IConfigurationRefresher refresher = null; @@ -242,13 +242,13 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Update sentinel key-value to trigger refreshAll operation sentinelKv.Value = "UpdatedSentinelValue"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Contains(LoggingConstants.RefreshFailedDueToKeyVaultError + "\nNo key vault credential or secret resolver callback configured, and no matching secret client could be found.", warningInvocation); } [Fact] - public void ValidateAggregateExceptionWithInnerOperationCanceledExceptionLoggedDuringRefresh() + public async Task ValidateAggregateExceptionWithInnerOperationCanceledExceptionLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -283,14 +283,14 @@ public void ValidateAggregateExceptionWithInnerOperationCanceledExceptionLoggedD FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.NotEqual("newValue1", config["TestKey1"]); Assert.Contains(LoggingConstants.RefreshFailedError, warningInvocation); } [Fact] - public void ValidateOperationCanceledExceptionLoggedDuringRefresh() + public async Task ValidateOperationCanceledExceptionLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -326,14 +326,14 @@ public void ValidateOperationCanceledExceptionLoggedDuringRefresh() using var cancellationSource = new CancellationTokenSource(); cancellationSource.Cancel(); - refresher.TryRefreshAsync(cancellationSource.Token).Wait(); + await refresher.TryRefreshAsync(cancellationSource.Token); Assert.NotEqual("newValue1", config["TestKey1"]); Assert.Contains(LoggingConstants.RefreshCanceledError, warningInvocation); } [Fact] - public void ValidateFailoverToDifferentEndpointMessageLoggedAfterFailover() + public async Task ValidateFailoverToDifferentEndpointMessageLoggedAfterFailover() { IConfigurationRefresher refresher = null; var mockClient1 = GetMockConfigurationClient(); @@ -381,7 +381,7 @@ public void ValidateFailoverToDifferentEndpointMessageLoggedAfterFailover() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1", config["TestKey1"]); Assert.Contains(LogHelper.BuildFailoverMessage(TestHelpers.PrimaryConfigStoreEndpoint.ToString(), TestHelpers.SecondaryConfigStoreEndpoint.ToString()), warningInvocation); @@ -393,14 +393,14 @@ public void ValidateFailoverToDifferentEndpointMessageLoggedAfterFailover() FirstKeyValue.Value = "TestValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1", config["TestKey1"]); Assert.Contains(LogHelper.BuildLastEndpointFailedMessage(TestHelpers.SecondaryConfigStoreEndpoint.ToString()), warningInvocation); } [Fact] - public void ValidateConfigurationUpdatedSuccessLoggedDuringRefresh() + public async Task ValidateConfigurationUpdatedSuccessLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -435,14 +435,14 @@ public void ValidateConfigurationUpdatedSuccessLoggedDuringRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1", config["TestKey1"]); Assert.Contains(LogHelper.BuildConfigurationUpdatedMessage(), invocation); } [Fact] - public void ValidateCorrectEndpointLoggedOnConfigurationUpdate() + public async Task ValidateCorrectEndpointLoggedOnConfigurationUpdate() { IConfigurationRefresher refresher = null; var mockClient1 = new Mock(); @@ -484,14 +484,14 @@ public void ValidateCorrectEndpointLoggedOnConfigurationUpdate() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); // We should see the second client's endpoint logged since the first client is backed off Assert.Contains(LogHelper.BuildKeyValueReadMessage(KeyValueChangeType.Modified, _kvCollection[0].Key, _kvCollection[0].Label, TestHelpers.SecondaryConfigStoreEndpoint.ToString().TrimEnd('/')), invocation); } [Fact] - public void ValidateCorrectKeyValueLoggedDuringRefresh() + public async Task ValidateCorrectKeyValueLoggedDuringRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -531,7 +531,7 @@ public void ValidateCorrectKeyValueLoggedDuringRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1", config["TestKey1"]); Assert.Contains(LogHelper.BuildKeyValueReadMessage(KeyValueChangeType.Modified, _kvCollection[0].Key, _kvCollection[0].Label, TestHelpers.PrimaryConfigStoreEndpoint.ToString().TrimEnd('/')), verboseInvocation); @@ -540,7 +540,7 @@ public void ValidateCorrectKeyValueLoggedDuringRefresh() } [Fact] - public void ValidateCorrectKeyVaultSecretLoggedDuringRefresh() + public async Task ValidateCorrectKeyVaultSecretLoggedDuringRefresh() { string _secretValue = "SecretValue from KeyVault"; Uri vaultUri = new Uri("https://keyvault-theclassics.vault.azure.net"); @@ -594,7 +594,7 @@ public void ValidateCorrectKeyVaultSecretLoggedDuringRefresh() } "; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Contains(LogHelper.BuildKeyVaultSecretReadMessage(_kvr.Key, _kvr.Label), verboseInvocation); Assert.Contains(LogHelper.BuildKeyVaultSettingUpdatedMessage(_kvr.Key), informationalInvocation); } diff --git a/tests/Tests.AzureAppConfiguration/MapTests.cs b/tests/Tests.AzureAppConfiguration/MapTests.cs index 140282b7..ea5b45ca 100644 --- a/tests/Tests.AzureAppConfiguration/MapTests.cs +++ b/tests/Tests.AzureAppConfiguration/MapTests.cs @@ -130,7 +130,7 @@ public void MapTransformKeyVaultValueBeforeAdapters() } [Fact] - public void MapTransformWithRefresh() + public async Task MapTransformWithRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -176,14 +176,14 @@ public void MapTransformWithRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1 mapped first", config["TestKey1"]); Assert.Equal("TestValue2 second", config["TestKey2"]); } [Fact] - public void MapTransformSettingKeyWithRefresh() + public async Task MapTransformSettingKeyWithRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -226,14 +226,14 @@ public void MapTransformSettingKeyWithRefresh() _kvCollection.Last().Value = "newValue2"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1 changed", config["newTestKey1"]); Assert.Equal("newValue2", config["TestKey2"]); } [Fact] - public void MapTransformSettingLabelWithRefresh() + public async Task MapTransformSettingLabelWithRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -274,14 +274,14 @@ public void MapTransformSettingLabelWithRefresh() _kvCollection.Last().Value = "newValue2"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1 changed", config["TestKey1"]); Assert.Equal("newValue2 changed", config["TestKey2"]); } [Fact] - public void MapTransformSettingCreateDuplicateKeyWithRefresh() + public async Task MapTransformSettingCreateDuplicateKeyWithRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -322,14 +322,14 @@ public void MapTransformSettingCreateDuplicateKeyWithRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("TestValue2 changed", config["TestKey2"]); Assert.Null(config["TestKey1"]); } [Fact] - public void MapCreateNewSettingWithRefresh() + public async Task MapCreateNewSettingWithRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -367,7 +367,7 @@ public void MapCreateNewSettingWithRefresh() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("mappedValue1", config["TestKey1"]); Assert.Equal("TestValue2", config["TestKey2"]); @@ -450,7 +450,7 @@ public void MapAsyncResolveKeyVaultReference() } [Fact] - public void MapTransformSettingKeyWithLogAndRefresh() + public async Task MapTransformSettingKeyWithLogAndRefresh() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -508,7 +508,7 @@ public void MapTransformSettingKeyWithLogAndRefresh() _kvCollection.Last().Value = "newValue2"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1 changed", config["newTestKey1"]); Assert.Equal("newValue2", config["TestKey2"]); diff --git a/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs b/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs index c94e877f..304a7e02 100644 --- a/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs +++ b/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs @@ -286,7 +286,7 @@ public void ProcessPushNotificationThrowsArgumentExceptions() } [Fact] - public void SyncTokenUpdatesCorrectNumberOfTimes() + public async Task SyncTokenUpdatesCorrectNumberOfTimes() { // Arrange var mockResponse = new Mock(); @@ -312,7 +312,7 @@ public void SyncTokenUpdatesCorrectNumberOfTimes() foreach (PushNotification pushNotification in _pushNotificationList) { refresher.ProcessPushNotification(pushNotification, TimeSpan.FromSeconds(0)); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); } var validNotificationKVWatcherCount = 8; @@ -324,7 +324,7 @@ public void SyncTokenUpdatesCorrectNumberOfTimes() } [Fact] - public void RefreshAsyncUpdatesConfig() + public async Task RefreshAsyncUpdatesConfig() { // Arrange var mockResponse = new Mock(); @@ -351,7 +351,7 @@ public void RefreshAsyncUpdatesConfig() FirstKeyValue.Value = "newValue1"; refresher.ProcessPushNotification(_pushNotificationList.First(), TimeSpan.FromSeconds(0)); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("newValue1", config["TestKey1"]); } diff --git a/tests/Tests.AzureAppConfiguration/RefreshTests.cs b/tests/Tests.AzureAppConfiguration/RefreshTests.cs index 48becbd9..298fa4b8 100644 --- a/tests/Tests.AzureAppConfiguration/RefreshTests.cs +++ b/tests/Tests.AzureAppConfiguration/RefreshTests.cs @@ -130,7 +130,7 @@ public void RefreshTests_RefreshRegisteredKeysAreLoadedOnStartup_CustomUseQuery( } [Fact] - public void RefreshTests_RefreshIsSkippedIfCacheIsNotExpired() + public async Task RefreshTests_RefreshIsSkippedIfCacheIsNotExpired() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -152,13 +152,13 @@ public void RefreshTests_RefreshIsSkippedIfCacheIsNotExpired() Assert.Equal("TestValue1", config["TestKey1"]); FirstKeyValue.Value = "newValue1"; - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("TestValue1", config["TestKey1"]); } [Fact] - public void RefreshTests_RefreshIsSkippedIfKvNotInSelectAndCacheIsNotExpired() + public async Task RefreshTests_RefreshIsSkippedIfKvNotInSelectAndCacheIsNotExpired() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClientSelectKeyLabel(); @@ -181,13 +181,13 @@ public void RefreshTests_RefreshIsSkippedIfKvNotInSelectAndCacheIsNotExpired() Assert.Equal("TestValue1", config["TestKey1"]); FirstKeyValue.Value = "newValue1"; - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("TestValue1", config["TestKey1"]); } [Fact] - public void RefreshTests_RefreshIsNotSkippedIfCacheIsExpired() + public async Task RefreshTests_RefreshIsNotSkippedIfCacheIsExpired() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -213,13 +213,13 @@ public void RefreshTests_RefreshIsNotSkippedIfCacheIsExpired() // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("newValue", config["TestKey1"]); } [Fact] - public void RefreshTests_RefreshAllFalseDoesNotUpdateEntireConfiguration() + public async Task RefreshTests_RefreshAllFalseDoesNotUpdateEntireConfiguration() { var keyValueCollection = new List(_kvCollection); IConfigurationRefresher refresher = null; @@ -249,7 +249,7 @@ public void RefreshTests_RefreshAllFalseDoesNotUpdateEntireConfiguration() // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("newValue", config["TestKey1"]); Assert.NotEqual("newValue", config["TestKey2"]); @@ -257,7 +257,7 @@ public void RefreshTests_RefreshAllFalseDoesNotUpdateEntireConfiguration() } [Fact] - public void RefreshTests_RefreshAllTrueUpdatesEntireConfiguration() + public async Task RefreshTests_RefreshAllTrueUpdatesEntireConfiguration() { var keyValueCollection = new List(_kvCollection); IConfigurationRefresher refresher = null; @@ -287,7 +287,7 @@ public void RefreshTests_RefreshAllTrueUpdatesEntireConfiguration() // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("newValue", config["TestKey1"]); Assert.Equal("newValue", config["TestKey2"]); @@ -295,7 +295,7 @@ public void RefreshTests_RefreshAllTrueUpdatesEntireConfiguration() } [Fact] - public void RefreshTests_RefreshAllTrueRemovesDeletedConfiguration() + public async Task RefreshTests_RefreshAllTrueRemovesDeletedConfiguration() { var keyValueCollection = new List(_kvCollection); var mockResponse = new Mock(); @@ -359,7 +359,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("newValue", config["TestKey1"]); Assert.Equal("TestValue2", config["TestKey2"]); @@ -367,7 +367,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o } [Fact] - public void RefreshTests_RefreshAllForNonExistentSentinelDoesNothing() + public async Task RefreshTests_RefreshAllForNonExistentSentinelDoesNothing() { var keyValueCollection = new List(_kvCollection); var mockResponse = new Mock(); @@ -433,7 +433,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // Validate that key-values registered for refresh were updated Assert.Equal("newValue1", config["TestKey1"]); @@ -444,7 +444,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o } [Fact] - public void RefreshTests_SingleServerCallOnSimultaneousMultipleRefresh() + public async void RefreshTests_SingleServerCallOnSimultaneousMultipleRefresh() { var keyValueCollection = new List(_kvCollection); var requestCount = 0; @@ -505,7 +505,8 @@ Response GetIfChanged(ConfigurationSetting setting, bool o var task1 = Task.Run(() => WaitAndRefresh(refresher, 1500)); var task2 = Task.Run(() => WaitAndRefresh(refresher, 3000)); var task3 = Task.Run(() => WaitAndRefresh(refresher, 4500)); - Task.WaitAll(task1, task2, task3); + + await Task.WhenAll(task1, task2, task3); Assert.Equal("newValue", config["TestKey1"]); Assert.Equal(2, requestCount); @@ -548,7 +549,7 @@ public void RefreshTests_RefreshAsyncThrowsOnRequestFailedException() } [Fact] - public void RefreshTests_TryRefreshAsyncReturnsFalseOnRequestFailedException() + public async Task RefreshTests_TryRefreshAsyncReturnsFalseOnRequestFailedException() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -577,14 +578,14 @@ public void RefreshTests_TryRefreshAsyncReturnsFalseOnRequestFailedException() // Wait for the cache to expire Thread.Sleep(1500); - bool result = refresher.TryRefreshAsync().Result; + bool result = await refresher.TryRefreshAsync(); Assert.False(result); Assert.NotEqual("newValue", config["TestKey1"]); } [Fact] - public void RefreshTests_TryRefreshAsyncUpdatesConfigurationAndReturnsTrueOnSuccess() + public async Task RefreshTests_TryRefreshAsyncUpdatesConfigurationAndReturnsTrueOnSuccess() { IConfigurationRefresher refresher = null; var mockClient = GetMockConfigurationClient(); @@ -610,14 +611,14 @@ public void RefreshTests_TryRefreshAsyncUpdatesConfigurationAndReturnsTrueOnSucc // Wait for the cache to expire Thread.Sleep(1500); - bool result = refresher.TryRefreshAsync().Result; + bool result = await refresher.TryRefreshAsync(); Assert.True(result); Assert.Equal("newValue", config["TestKey1"]); } [Fact] - public void RefreshTests_TryRefreshAsyncReturnsFalseForAuthenticationFailedException() + public async Task RefreshTests_TryRefreshAsyncReturnsFalseForAuthenticationFailedException() { IConfigurationRefresher refresher = null; var mockResponse = new Mock(); @@ -654,13 +655,13 @@ public void RefreshTests_TryRefreshAsyncReturnsFalseForAuthenticationFailedExcep Thread.Sleep(1500); // First call to GetConfigurationSettingAsync does not throw - Assert.True(refresher.TryRefreshAsync().Result); + Assert.True(await refresher.TryRefreshAsync()); // Wait for the cache to expire Thread.Sleep(1500); // Second call to GetConfigurationSettingAsync throws KeyVaultReferenceException - Assert.False(refresher.TryRefreshAsync().Result); + Assert.False(await refresher.TryRefreshAsync()); } [Fact] @@ -774,7 +775,7 @@ await Assert.ThrowsAsync(async () => } [Fact] - public void RefreshTests_SentinelKeyNotUpdatedOnRefreshAllFailure() + public async Task RefreshTests_SentinelKeyNotUpdatedOnRefreshAllFailure() { var keyValueCollection = new List(_kvCollection); var mockResponse = new Mock(); @@ -827,7 +828,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Wait for the cache to expire Thread.Sleep(1500); - bool firstRefreshResult = refresher.TryRefreshAsync().Result; + bool firstRefreshResult = await refresher.TryRefreshAsync(); Assert.False(firstRefreshResult); Assert.Equal("TestValue1", config["TestKey1"]); @@ -837,7 +838,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Wait for the cache to expire Thread.Sleep(1500); - bool secondRefreshResult = refresher.TryRefreshAsync().Result; + bool secondRefreshResult = await refresher.TryRefreshAsync(); Assert.True(secondRefreshResult); Assert.Equal("newValue", config["TestKey1"]); @@ -846,7 +847,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o } [Fact] - public void RefreshTests_RefreshAllTrueForOverwrittenSentinelUpdatesEntireConfiguration() + public async Task RefreshTests_RefreshAllTrueForOverwrittenSentinelUpdatesEntireConfiguration() { var keyValueCollection = new List(_kvCollection); IConfigurationRefresher refresher = null; @@ -878,7 +879,7 @@ public void RefreshTests_RefreshAllTrueForOverwrittenSentinelUpdatesEntireConfig // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); Assert.Equal("newValue", config["TestKey1"]); Assert.Equal("newValue", config["TestKey2"]); @@ -887,7 +888,7 @@ public void RefreshTests_RefreshAllTrueForOverwrittenSentinelUpdatesEntireConfig } [Fact] - public void RefreshTests_RefreshAllFalseForOverwrittenSentinelUpdatesConfig() + public async Task RefreshTests_RefreshAllFalseForOverwrittenSentinelUpdatesConfig() { var keyValueCollection = new List(_kvCollection); ConfigurationSetting refreshRegisteredSetting = keyValueCollection.FirstOrDefault(s => s.Key == "TestKeyWithMultipleLabels" && s.Label == "label1"); @@ -920,7 +921,7 @@ public void RefreshTests_RefreshAllFalseForOverwrittenSentinelUpdatesConfig() // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // Validate that refresh registered key-value was updated Assert.Equal("TestValue1", config["TestKey1"]); @@ -930,7 +931,7 @@ public void RefreshTests_RefreshAllFalseForOverwrittenSentinelUpdatesConfig() } [Fact] - public void RefreshTests_RefreshRegisteredKvOverwritesSelectedKv() + public async Task RefreshTests_RefreshRegisteredKvOverwritesSelectedKv() { var keyValueCollection = new List(_kvCollection); ConfigurationSetting refreshAllRegisteredSetting = keyValueCollection.FirstOrDefault(s => s.Key == "TestKeyWithMultipleLabels" && s.Label == "label1"); @@ -963,7 +964,7 @@ public void RefreshTests_RefreshRegisteredKvOverwritesSelectedKv() // Wait for the cache to expire Thread.Sleep(1500); - refresher.RefreshAsync().Wait(); + await refresher.RefreshAsync(); // Validate that only the refresh registered key-value was updated Assert.Equal("TestValue1", config["TestKey1"]); From 487c6c87f2bbe05b20fd7a77e122659efeaee22e Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:55:15 +0800 Subject: [PATCH 2/7] Stop using packages of deprecated version and version with vulnerability in example projects (#560) * update package * update package --- .../ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj | 6 +++--- examples/ConsoleApplication/ConsoleApplication.csproj | 4 ++-- .../Tests.AzureAppConfiguration.csproj | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj b/examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj index ff4b0398..ddcb2b93 100644 --- a/examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj +++ b/examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/examples/ConsoleApplication/ConsoleApplication.csproj b/examples/ConsoleApplication/ConsoleApplication.csproj index be38de42..bd4756fa 100644 --- a/examples/ConsoleApplication/ConsoleApplication.csproj +++ b/examples/ConsoleApplication/ConsoleApplication.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj b/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj index b0aef653..9b0f17c0 100644 --- a/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj +++ b/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj @@ -11,7 +11,7 @@ - + From 6a682ff799a0c25374e54b0d74632140b62c1891 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Sat, 22 Jun 2024 02:44:26 +0800 Subject: [PATCH 3/7] fix xunit1031 and netsdk1210 (#561) --- ...ns.Configuration.AzureAppConfiguration.csproj | 2 +- .../FeatureManagementTests.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj index 466c58be..12b99a00 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj @@ -48,7 +48,7 @@ ..\..\AzureAppConfigurationRules.ruleset true - true + true diff --git a/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs b/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs index 809187fd..abcb7595 100644 --- a/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs +++ b/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs @@ -618,7 +618,7 @@ public void PreservesDefaultQuery() } [Fact] - public async Task QueriesFeatureFlags() + public void QueriesFeatureFlags() { var mockTransport = new MockTransport(req => { @@ -1266,7 +1266,7 @@ public async Task SelectAndRefreshSingleFeatureFlag() } [Fact] - public void ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefresh() + public async Task ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefresh() { IConfigurationRefresher refresher = null; var featureFlags = new List { _kv2 }; @@ -1326,14 +1326,14 @@ public void ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefresh() eTag: new ETag("c3c231fd-39a0-4cb6-3237-4614474b92c1" + "f")); Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("AllUsers", config["FeatureManagement:MyFeature:EnabledFor:0:Name"]); Assert.Contains(LogHelper.BuildFeatureFlagReadMessage("myFeature1", null, TestHelpers.PrimaryConfigStoreEndpoint.ToString().TrimEnd('/')), verboseInvocation); Assert.Contains(LogHelper.BuildFeatureFlagUpdatedMessage("myFeature1"), informationalInvocation); featureFlags.RemoveAt(0); Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Null(config["FeatureManagement:MyFeature:EnabledFor:0:Name"]); Assert.Contains(LogHelper.BuildFeatureFlagReadMessage("myFeature1", null, TestHelpers.PrimaryConfigStoreEndpoint.ToString().TrimEnd('/')), verboseInvocation); @@ -1341,7 +1341,7 @@ public void ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefresh() } [Fact] - public void ValidateFeatureFlagsUnchangedLogged() + public async Task ValidateFeatureFlagsUnchangedLogged() { IConfigurationRefresher refresher = null; var featureFlags = new List { _kv2 }; @@ -1387,13 +1387,13 @@ public void ValidateFeatureFlagsUnchangedLogged() FirstKeyValue.Value = "newValue1"; Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("SuperUsers", config["FeatureManagement:MyFeature2:EnabledFor:0:Name"]); Assert.Contains(LogHelper.BuildFeatureFlagsUnchangedMessage(TestHelpers.PrimaryConfigStoreEndpoint.ToString().TrimEnd('/')), verboseInvocation); } [Fact] - public void MapTransformFeatureFlagWithRefresh() + public async Task MapTransformFeatureFlagWithRefresh() { ConfigurationSetting _kv = ConfigurationModelFactory.ConfigurationSetting( key: FeatureManagementConstants.FeatureFlagMarker + "myFeature", @@ -1499,7 +1499,7 @@ public void MapTransformFeatureFlagWithRefresh() eTag: new ETag("c3c231fd-39a0-4cb6-3237-4614474b92c1" + "f")); Thread.Sleep(CacheExpirationTime); - refresher.TryRefreshAsync().Wait(); + await refresher.TryRefreshAsync(); Assert.Equal("newValue1", config["TestKey1"]); Assert.Equal("NoUsers", config["FeatureManagement:MyFeature:EnabledFor:0:Name"]); From 96a5e5a07b8d4b4aa55d31bcab14219ee6912a04 Mon Sep 17 00:00:00 2001 From: Amer Jusupovic <32405726+amerjusupovic@users.noreply.github.com> Date: Fri, 21 Jun 2024 12:40:17 -0700 Subject: [PATCH 4/7] Add handling for FormatException thrown by invalid feature flag json (#551) * add log for formatexception from invalid feature flag json * remove capitalized json * remove unused using * fix comments * fix constant reference --- .../AzureAppConfigurationProvider.cs | 7 +++++++ .../Constants/LoggingConstants.cs | 1 + .../FeatureManagement/FeatureManagementKeyValueAdapter.cs | 2 +- .../LogHelper.cs | 5 +++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs index 9cf9947b..182c819a 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs @@ -492,6 +492,12 @@ public async Task TryRefreshAsync(CancellationToken cancellationToken) return false; } + catch (FormatException fe) + { + _logger.LogWarning(LogHelper.BuildRefreshFailedDueToFormattingErrorMessage(fe.Message)); + + return false; + } return true; } @@ -634,6 +640,7 @@ exception is KeyVaultReferenceException || exception is TimeoutException || exception is OperationCanceledException || exception is InvalidOperationException || + exception is FormatException || ((exception as AggregateException)?.InnerExceptions?.Any(e => e is RequestFailedException || e is OperationCanceledException) ?? false))) diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/LoggingConstants.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/LoggingConstants.cs index 41c56ca3..86576a48 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/LoggingConstants.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/LoggingConstants.cs @@ -15,6 +15,7 @@ internal class LoggingConstants public const string RefreshFailedDueToKeyVaultError = "A refresh operation failed while resolving a Key Vault reference."; public const string PushNotificationUnregisteredEndpoint = "Ignoring the push notification received for the unregistered endpoint"; public const string FallbackClientLookupError = "Failed to perform fallback client lookup."; + public const string RefreshFailedDueToFormattingError = "A refresh operation failed due to a formatting error."; // Successful update, debug log level public const string RefreshKeyValueRead = "Key-value read from App Configuration."; diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs index a4f64d6b..5b0a6a96 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs @@ -188,7 +188,7 @@ private FeatureFlag ParseFeatureFlag(string settingKey, string settingValue) } catch (JsonException e) { - throw new FormatException(settingKey, e); + throw new FormatException(string.Format(ErrorMessages.FeatureFlagInvalidFormat, settingKey), e); } return featureFlag; diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/LogHelper.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/LogHelper.cs index 113a1499..e7429a9e 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/LogHelper.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/LogHelper.cs @@ -89,5 +89,10 @@ public static string BuildFallbackClientLookupFailMessage(string exceptionMessag { return $"{LoggingConstants.FallbackClientLookupError}\n{exceptionMessage}"; } + + public static string BuildRefreshFailedDueToFormattingErrorMessage(string exceptionMessage) + { + return $"{LoggingConstants.RefreshFailedDueToFormattingError}\n{exceptionMessage}"; + } } } From 73e8838b6c5dabdf71165dcb674274dadc7b185e Mon Sep 17 00:00:00 2001 From: Amer Jusupovic <32405726+amerjusupovic@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:42:06 -0700 Subject: [PATCH 5/7] update azure.security.keyvault.secrets (#572) --- ...rosoft.Extensions.Configuration.AzureAppConfiguration.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj index 12b99a00..ab923a8b 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj @@ -16,7 +16,7 @@ - + From 5c44ff69c09207915d2155a98487907ea3ac13f3 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:19:51 +0800 Subject: [PATCH 6/7] Detect SignalR usage for request tracing (#570) * collect usage of SignalR * fix typo * fix typo * rename signalR --- .../AzureAppConfigurationProvider.cs | 15 ++++++++++----- .../Constants/RequestTracingConstants.cs | 3 +++ .../RequestTracingOptions.cs | 5 +++++ .../TracingUtils.cs | 5 +++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs index 182c819a..0868ea14 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs @@ -26,7 +26,7 @@ internal class AzureAppConfigurationProvider : ConfigurationProvider, IConfigura { private bool _optional; private bool _isInitialLoadComplete = false; - private bool _isFeatureManagementVersionInspected; + private bool _isAssemblyInspected; private readonly bool _requestTracingEnabled; private readonly IConfigurationClientManager _configClientManager; private AzureAppConfigurationOptions _options; @@ -189,7 +189,7 @@ public async Task RefreshAsync(CancellationToken cancellationToken) try { // FeatureManagement assemblies may not be loaded on provider startup, so version information is gathered upon first refresh for tracing - EnsureFeatureManagementVersionInspected(); + EnsureAssemblyInspected(); var utcNow = DateTimeOffset.UtcNow; IEnumerable cacheExpiredWatchers = _options.ChangeWatchers.Where(changeWatcher => utcNow >= changeWatcher.CacheExpires); @@ -1186,17 +1186,22 @@ private IEnumerable GetCurrentKeyValueCollection(string ke return currentKeyValues; } - private void EnsureFeatureManagementVersionInspected() + private void EnsureAssemblyInspected() { - if (!_isFeatureManagementVersionInspected) + if (!_isAssemblyInspected) { - _isFeatureManagementVersionInspected = true; + _isAssemblyInspected = true; if (_requestTracingEnabled && _requestTracingOptions != null) { _requestTracingOptions.FeatureManagementVersion = TracingUtils.GetAssemblyVersion(RequestTracingConstants.FeatureManagementAssemblyName); _requestTracingOptions.FeatureManagementAspNetCoreVersion = TracingUtils.GetAssemblyVersion(RequestTracingConstants.FeatureManagementAspNetCoreAssemblyName); + + if (TracingUtils.GetAssemblyVersion(RequestTracingConstants.SignalRAssemblyName) != null) + { + _requestTracingOptions.IsSignalRUsed = true; + } } } } diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs index 9ab29637..f1da875b 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs @@ -30,6 +30,7 @@ internal class RequestTracingConstants public const string KeyVaultConfiguredTag = "UsesKeyVault"; public const string KeyVaultRefreshConfiguredTag = "RefreshesKeyVault"; public const string ReplicaCountKey = "ReplicaCount"; + public const string SignalRUsedTag = "UsesSignalR"; public const string DiagnosticHeaderActivityName = "Azure.CustomDiagnosticHeaders"; public const string CorrelationContextHeader = "Correlation-Context"; @@ -37,5 +38,7 @@ internal class RequestTracingConstants public const string FeatureManagementAssemblyName = "Microsoft.FeatureManagement"; public const string FeatureManagementAspNetCoreAssemblyName = "Microsoft.FeatureManagement.AspNetCore"; + + public const string SignalRAssemblyName = "Microsoft.AspNetCore.SignalR"; } } diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/RequestTracingOptions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/RequestTracingOptions.cs index 27af8fae..b5769b9d 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/RequestTracingOptions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/RequestTracingOptions.cs @@ -46,5 +46,10 @@ internal class RequestTracingOptions /// Version of the Microsoft.FeatureManagement.AspNetCore assembly, if present in the application. /// public string FeatureManagementAspNetCoreVersion { get; set; } + + /// + /// Flag to indicate whether Microsoft.AspNetCore.SignalR assembly is present in the application. + /// + public bool IsSignalRUsed { get; set; } = false; } } diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs index 3ca5271f..bbf8511c 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs @@ -160,6 +160,11 @@ private static string CreateCorrelationContextHeader(RequestType requestType, Re correlationContextTags.Add(RequestTracingConstants.KeyVaultRefreshConfiguredTag); } + if (requestTracingOptions.IsSignalRUsed) + { + correlationContextTags.Add(RequestTracingConstants.SignalRUsedTag); + } + var sb = new StringBuilder(); foreach (KeyValuePair kvp in correlationContextKeyValues) From 0c9e17a9e04b7be98388db7c7dc6e0dffc37939e Mon Sep 17 00:00:00 2001 From: Amer Jusupovic <32405726+amerjusupovic@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:44:13 -0700 Subject: [PATCH 7/7] update package versions to 7.3.0 (#575) --- .../Microsoft.Azure.AppConfiguration.AspNetCore.csproj | 2 +- .../Microsoft.Azure.AppConfiguration.Functions.Worker.csproj | 2 +- ...rosoft.Extensions.Configuration.AzureAppConfiguration.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj b/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj index c081cacd..5c33c144 100644 --- a/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj +++ b/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj @@ -21,7 +21,7 @@ - 7.2.0 + 7.3.0 diff --git a/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj b/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj index 90831b4d..43d8d181 100644 --- a/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj +++ b/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj @@ -24,7 +24,7 @@ - 7.2.0 + 7.3.0 diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj index ab923a8b..da78f0e9 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj @@ -34,7 +34,7 @@ - 7.2.0 + 7.3.0