-
Notifications
You must be signed in to change notification settings - Fork 34
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
Allow selection and sentinel keys on feature flags #163
Comments
Hi there. Have you had any time to look into this request? On further thoughts, we think that having access to the currently internal interface This way, we could even create a custom adapter (we have a few use cases for that) and add a new implementation without accessing any internal stuff. If needed, we could provide a PR, even if this seems to be quite a minor code change, and is probably more of a design decision. |
@RemyBoyer I apologize this completely slipped through the cracks. Thanks for the detailed explanation of your scenario. I understand that applications may only want to retrieve the subset of feature flags that they need. When using var configuration = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
{
options.Connect(connectionString);
options.UseFeatureFlags(featureFlagOptions =>
{
featureFlagOptions.FeatureFlagPrefix = "MyApp/*"; // Refers to ".appconfig.featureflag/MyApp/*"
featureFlagOptions.Label = "MyLabel";
featureFlagOptions.CacheExpirationInterval = cacheExpirationTimeSpan;
});
options.UseFeatureFlags(featureFlagOptions =>
{
featureFlagOptions.FeatureFlagPrefix = "Common/MyFeatureFlag"; // Refers to ".appconfig.featureflag/Common/MyFeatureFlag"
featureFlagOptions.Label = "MyLabel";
featureFlagOptions.CacheExpirationInterval = cacheExpirationTimeSpan;
});
})
.Build(); |
@abhilasharora Thanks for your reply! Unfortunately, I don't think it would be sufficient. Indeed, we have an N-N relationship between feature flags and what we call "scopes", which would in your case correspond to prefixes. Here's an example: As long as Unfortunately, as soon as we add the scope That's why in my proposed solution, scopes are not prefixes but rather refresh keys. I hope this is clear 😅 Please let me know if you need additional information. |
Hi @abhilasharora, have you had time to consider my response? After more than a year at building this as a side project when we had some free time at work, we are reaching the completion of our MVP, and need to know if this feature can make it to the App Configuration nuget. Having this feature would clearly simplify some of our code and configuration. Thanks in advance! |
Hey @RemyBoyer I took a look at this and here's what I came up with. Mostly I'm close to what @abhilasharora suggested.
I would recommend that you use the push model for refreshing configuration/feature flags. This is the best bet for scalability since no polling is needed; not even for sentinel keys. Documentation is in the works here: https://github.com/MicrosoftDocs/azure-docs-pr/pull/127339/files?short_path=a0a5347#diff-a0a534713c23d4e3ed6659ef5b36d60a79f74b15b072b482fadc19e60484c8a4 I took a look at your PR. Even if the polling model for refresh is used instead of push model, I don't think we need You mentioned the automatic paginated scanning of feature flags. We do need to provide a way to disable the automatic registration of feature flags for polling when UseFeatureFlags is called.
When we use feature flags we pull all key-values with a given prefix ".appconfig.featureflag/". We also wire up a polling/scan refresh for these key-values. This paradigm of working with prefixes to use a set of feature flags has already been established. Adding a Given the requests, having taken a look at your PR, and considering the current design, here is what I think we can do. It is mostly what @abhilasharora suggested. Here though we register a few sentinel keys for your idea of "scopes". We also disable polling refresh for feature flags so that only the sentinel keys are checked.
|
Hi @jimmyca15, thanks for your response.
This is a very interesting capability. Unfortunately, I can't access this pull request. I'm a bit concerned by the engineering overhead that might be required for this push capability to work, though. If that overhead doesn't scale well (with the number of apps that will use the az app config), it might not be worth it. I guess it will be much clearer as soon as I have access to the documentation. Regarding usage of the "prefix" that you suggest, I understand how it handles both the selection and the refresh. The issue we have is that it would not fit by default to our N-N relationship between the feature flags and the scopes (which are mostly groups of executable apps). With this denormalization, I think we could indeed use the code you've just showed! I'm updating the code to prepare for this usage. I have a few questions:
|
For the push model, the documentation can be found here. This is our recommended approach for scenarios where there are a large number of instances retrieving configuration from App Configuration, or if there are concerns about exceeding the rate limits. For the poll model, the |
@abhilasharora thanks for the documentation. We'll look into that Regarding the I didn't understand that those proposals were "new", though. If you can add it to your roadmap, then please do so! May we help on the implementation? |
@RemyBoyer we are looking into it and should be able to get to it ourselves. I looked again at the proposal, and I don't think that |
@jimmyca15 I agree with you, having a very high expiration won't be that much different than having none at all. The key part is the |
It wouldn't automatically, but adding a One thing to consider when trimming prefixes is that if two feature flags have a matching name after trimming the prefix, their value can be indeterministic. Is this okay in your case? |
Yes, it's ok in our case, since the feature flag names are guaranteed to be unique, as they are created with a specific app that enforces this. I guess it's how it works with the normal settings anyway? |
Yes. |
@RemyBoyer, the feature has been released in package version 4.3.0-preview:
Please let us know if you have any feedback on the new functionality. |
@avanigupta Great news, thank you! I'll check it out asap |
@avanigupta, I've tested the changes I have a few feedbacks: one regarding performance and two other ones regarding usage. For a bit of context, here's how I use the new and existing features to achieve the goal stated in the original request: options.UseFeatureFlags(options =>
{
options.Select($"{scope}/*");
options.TrimFeatureFlagPrefix($".appconfig.featureflag/{scope}");
options.CacheExpirationInterval = TimeSpan.FromDays(1); // something very long, as the sentinel does the job of invalidation
});
options.ConfigureRefresh(options =>
{
options.Register($".appconfig.featureflag-scope/{scope}/.sentinel", true);
}); Loading issueThe issue with this is that despite selecting a specific prefix, the library still loads the entire AAC data. I suppose that this is not the intended behavior. As the original request was to avoid downloading extraneous feature flags, both for performance considerations, but also to "scope" feature flags, so that the consuming apps won't see flags that are not theirs. I tried to fix this behavior and found two ways. bool useDefaultQuery = !_options.KeyValueSelectors.Any(selector => selector.KeyFilter != FeatureManagementConstants.FeatureFlagMarker + "*"); It's actually the proposal I made in my PR. The second solution is to add a dummy options.Select($"non-existing"); // options is AzureAppConfigurationOptions and not FeatureFlagOptions Obviously, this trick doesn't seem ideal, but at least with this I can test the expected loading behavior, without having to change the library.
|
Thank you for the awesome feedback @RemyBoyer Loading issueThe feedback is noted and we'll think about it a bit more but want to offer some details. AAC provides settings and feature flags. By default, just calling In the past, we have suggested users who only want to query feature flags to have a structure like the following. It is pretty much the
Select and TrimFeatureFlagPrefix feedbackThis one is interesting. Are you creating your feature flags manually/programatically? Feature flag objects in AAC have an It seems that your feature flags have ids that start with ".appconfig.featureflag/" ? Select and LabelI see. Thanks for letting us know you hit this. A tricky part about querying across labels is that the same key can be retrieved from multiple labels. With a label filter of "*" the resulting key (in this case feature flag) that ends up in the applications configuration can be nondeterministic. This is not something that we want to introduce into the system. Our suggestion for composition of multiple labels is to be explicit through the use of multiple select invocations.
|
Hi @jimmyca15, thank you for your response. Loading issueOk, I understand your point, and wasn't aware of this intention. But since I have a way of enforcing this, it's not a blocker. Select and TrimFeatureFlagPrefix feedbackOn this one, I misunderstood what So my new options are:
I don't think the second solution adds any value. Do you have an opinion on this? Select and LabelOh, I didn't see that With these three updates, I now have something that's behaving as I intended it to! Thanks a lot for your detailed and swift response. |
If this works for you this is what I would opt for.
Thank you for the continuous, thorough feedback. We are happy to help. Please let us know if you find any further room for improvement. |
Since you're asking @jimmyca15, there is another issue that's important to us: microsoft/FeatureManagement-Dotnet#28 The solution we have chosen right now to bypass it is to fork the FeatureManagement libs. |
@RemyBoyer Regarding this issue, since |
Hi everyone,
We are currently building a feature flag infrastructure for all our applications. We want to use AppConfiguration, AppConfiguration-DotnetProvider and FeatureManagement-Dotnet to store and check the feature flags on the applications. We'll build our own feature flag management app though, to provide advanced logic (custom filters, audit, authentication/authorization, more...) to our internal users.
Since we are in a micro-services environment, we would like to reuse a single Azure App Configuration to decrease the costs and, hopefully, the infrastructure complexity.
We would ideally like to use and watch feature flags the same way it's done with "classic" app configuration usage.
For example, with the SDK we can currently do this:
Bu this can't be done use feature flags.
The main reasons we would like to do this would be:
Indeed, putting aside the overload that it surely represents on the AppConfiguration instance, it would also require multiple calls for each multiple of 100 feature flags, because of paging. Since our instance will be used by many apps, we expect it to contains many feature flags. If we imagine the app containing 1000 feature flags, this would mean that each app has to make 10 calls every 30s just to check if something has changed. We would break the 20k max requests per hour with just 17 apps.
Of course, this could mitigated by increasing the cache expiration, but we'd loose reactivity, with doesn't seems to be a good tradeoff.
Indeed, with the currently implemented feature flag configuration, the app watches all the feature flags. This means that when a feature flag used by app A is updated, it will be watched & downloaded by app B, even if it doesn't use it.
For these reasons, we'd like to be able to use explicit
.Select
and.Register
, which will eliminate those two drawbacks by providing the ability to select only the feature flags that are useful to the app, and by using sentinel keys that will be automatically updated by our Feature Flags management app.We actually managed to enable this by copying and adapting this method
AppConfiguration-DotnetProvider/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationOptions.cs
Line 138 in d19492d
into something like this:
As you can see, this code isn't pretty, but quite simple.
Additionally to
FeatureManagementKeyValueAdapter
and_adapters
which are respectivelyinternal
andprivate
, there is one additional hack which consists of using a different prefix for the feature flags, that can be seen onFeatureManagementConstants.FeatureFlagMarker
.This is necessary because there is a check here that forces a full scanning during refresh if one of the watched key filter starts with
.appconfig.featureflag/
:AppConfiguration-DotnetProvider/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs
Line 151 in d19492d
By putting all of our feature flags under
.appconfig.featureflag.my/
, we workaround this check.So my final questions would be:
AzureAppConfigurationOptions.Select
andAzureAppConfigurationRefreshOptions.Register
on feature flags usage? It could probably be additional properties/methods onFeatureFlagOptions
, or perhaps another overload (or anything you could think of!).private/internal
dependencies, so we can implement it ourselves? This would include exposing some way of addingFeatureManagementKeyValueAdapter
, and also, ideally, provide a way to disable the global scan onAzureAppConfigurationProvider.LoadAll
.The text was updated successfully, but these errors were encountered: