-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RegisterAll
API to enable monitoring collections of key-values for refresh
#574
Conversation
…otnetProvider into ajusupovic/collection-monitoring
…otnetProvider into ajusupovic/collection-monitoring
/// <summary> | ||
/// For use in tests only. An optional class used to process pageable results from Azure App Configuration. | ||
/// </summary> | ||
internal IPageableConfigurationSettings PageableConfigurationSettings { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggested this name (IPageableConfigurationSettings), and I think it was a bad suggestion. Because this is not configuration settings, it is indeed something that iterates through pages. The original name IConfigurationSettingsPageIterator
would be better, or something along those lines.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Outdated
Show resolved
Hide resolved
bool hasWatchers = watchers.Any(); | ||
TimeSpan minWatcherRefreshInterval = hasWatchers ? watchers.Min(w => w.RefreshInterval) : TimeSpan.MaxValue; | ||
|
||
if (options.RegisterAllEnabled) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The embedded ternary condition in the else
statement makes more sense to be a part of the upper if/else.
if (registerAllEnabled)
{
}
else if (watchers.Any())
{
}
else
{
}
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Outdated
Show resolved
Hide resolved
|
||
foreach (KeyValueWatcher changeWatcher in refreshableWatchers.Concat(refreshableMultiKeyWatchers)) | ||
// Invalidate all the cached KeyVault secrets | ||
foreach (IKeyValueAdapter adapter in _options.Adapters) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do deleted flags get removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
discussed offline, lost this along the way when restructuring the refresh methods. I'll try checking the existing data and using that to decide whether the setting for that flag's key should be updated. Might need a new data structure/method for this
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Outdated
Show resolved
Hide resolved
@@ -22,12 +22,14 @@ internal class LoggingConstants | |||
public const string RefreshKeyVaultSecretRead = "Secret read from Key Vault for key-value."; | |||
public const string RefreshFeatureFlagRead = "Feature flag read from App Configuration."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, will remove
ffKeys, | ||
cancellationToken).ConfigureAwait(false); | ||
|
||
logInfoBuilder.Append(LogHelper.BuildFeatureFlagsUpdatedMessage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see anywhere that we logged feature flag updates as info before. Am I missing it.
Also, why
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had a LogFeatureFlagUpdated
message when refreshing individual flags in the ConfigurationClientExtensions
file, so I thought it might make sense to log the collection being updated since it seems like whenever we update a value (kv, flag, secret) we would log it as info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. In that case, I see for configuration we log "Configuration reloaded.", but for flags it is currently "Feature flags updated." It seems to me we should be consistent and log "Feature flags reloaded."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, they both do a full reload so it makes sense
if (haveCollectionsChanged) | ||
{ | ||
return haveCollectionsChanged; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (haveCollectionsChanged) | |
{ | |
return haveCollectionsChanged; | |
} | |
if (haveCollectionsChanged) | |
{ | |
return true; | |
} |
@@ -376,18 +406,40 @@ public AzureAppConfigurationOptions ConfigureClientOptions(Action<ConfigurationC | |||
/// <param name="configure">A callback used to configure Azure App Configuration refresh options.</param> | |||
public AzureAppConfigurationOptions ConfigureRefresh(Action<AzureAppConfigurationRefreshOptions> configure) | |||
{ | |||
if (RegisterAllEnabled) | |||
{ | |||
throw new ArgumentException($"{nameof(ConfigureRefresh)}() cannot be invoked multiple times when {nameof(AzureAppConfigurationRefreshOptions.RegisterAll)} has been invoked."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be an invalid operation exception. There aren't any invalid arguments.
|
||
if (!isRegisterCalled && !RegisterAllEnabled) | ||
{ | ||
throw new ArgumentException($"{nameof(ConfigureRefresh)}() must register at least one key-value for refresh or enable refresh of all selected key-values."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that one must either call Register
or RegisterAll
, if so then I think it would be helpful to mention that explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, since we required calling Register
before, so now at least one should be called. I can update it to mention the specific APIs instead of this description in the exception
{ | ||
throw new ArgumentException($"{nameof(ConfigureRefresh)}() must have at least one key-value registered for refresh."); | ||
throw new ArgumentException($"Cannot call both {nameof(AzureAppConfigurationRefreshOptions.RegisterAll)} and " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InvalidOperationException.
|
||
if (!isRegisterCalled && !RegisterAllEnabled) | ||
{ | ||
throw new ArgumentException($"{nameof(ConfigureRefresh)}() must call either {nameof(AzureAppConfigurationRefreshOptions.Register)}()" + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also be an invalid operation exception since there are no invalid arguments.
…tants to match behavior
@@ -10,5 +10,6 @@ internal class ErrorMessages | |||
public const string FeatureFlagInvalidJsonProperty = "Invalid property '{0}' for feature flag. Key: '{1}'. Found type: '{2}'. Expected type: '{3}'."; | |||
public const string FeatureFlagInvalidFormat = "Invalid json format for feature flag. Key: '{0}'."; | |||
public const string InvalidKeyVaultReference = "Invalid Key Vault reference."; | |||
public const string InvalidConfigurationSettingPage = "Invalid page while loading configuration settings."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used. File changes can be reverted.
This PR adds the new
RegisterAll
API to monitor any key-values added withAzureAppConfigurationOptions.Select
for refresh as a collection, but it will also begin monitoring feature flags as a collection instead of on an individual basis. Consequently, feature flag changes will no longer be logged on an individual basis. This solves an existing issue.