Skip to content
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

Would like to understand the default percentage option under Targeting filter #527

Open
sathishkumarkaliavaradhan opened this issue Jan 23, 2025 · 22 comments
Labels
good first issue Good for newcomers

Comments

@sathishkumarkaliavaradhan

Hi All,

I would like to understand how the default percentage works? like within 1 hours if 10 calls made then 5 calls will get true and 5 calls get false?

I haven't set the seed and user groups only set the default percentage.

Thanks,
Sathishkumar

@jimmyca15
Copy link
Member

Hi @sathishkumarkaliavaradhan

The default percentage determines the probability that a feature flag will be enabled for any given request. If you set the default percentage to 50%, it means that, on average, 50% of the calls will return true (feature enabled) and 50% will return false (feature disabled).

However, this doesn’t guarantee an exact split within a specific timeframe or number of calls. For example, if 10 calls are made within an hour, it’s possible that not exactly 5 will return true and 5 will return false. The distribution is random, so you might see variations like 6 true and 4 false, or 3 true and 7 false, etc.

@sathishkumarkaliavaradhan
Copy link
Author

@jimmyca15 Thanks for the reply.

The default percentage determines the probability that a feature flag will be enabled for any given request. If you set the default percentage to 50%, it means that, on average, 50% of the calls will return true (feature enabled) and 50% will return false (feature disabled).

In our case we are using in our client WPF application, and App configuration SDK calling the CDN instead of Azure App configuration API. we see the CDN has the below configuration

"clientFilters": [ { "name": "DeviceFilter", "parameters": { "AppVersion": "5.5.0.0" } }, { "name": "Microsoft.Targeting", "parameters": { "Audience": { "Users": [], "Groups": [], "DefaultRolloutPercentage": 50 } } } ],

In this case how does SDK handle the DefaultRolloutPercentage of 50% rollout?

@zhiyuanliang-ms zhiyuanliang-ms added the good first issue Good for newcomers label Jan 29, 2025
@zhiyuanliang-ms
Copy link
Contributor

zhiyuanliang-ms commented Jan 29, 2025

Hi, @sathishkumarkaliavaradhan

The targeting filter is based on targeting context. For more information, please go to doc

We have algorithm to determine whether the certain targeting context should be targeted of not, more specificly speaking, which percentage where the targeting context will fall. And the targeting behavior is "sticky", which means the same targeting context will always fall into the same percentage. Worth to mention that the algorithm is consistent across all microsoft feature management libraries of all languages.

"clientFilters": [ { "name": "DeviceFilter", "parameters": { "AppVersion": "5.5.0.0" } }, { "name": "Microsoft.Targeting", "parameters": { "Audience": { "Users": [], "Groups": [], "DefaultRolloutPercentage": 50 } } } ],

In this case how does SDK handle the DefaultRolloutPercentage of 50% rollout?

In your example, you have two feature filters, by default, the filter behavior should be "if any filter is passed, then the feature flag is considered as enabled". For more information, please go to doc.

For the targeting filter, you should assign/generate a targeting context for each call.

like within 1 hours if 10 calls made then 5 calls will get true and 5 calls get false?

If all 10 calls come from the same device or user, then all of them should be targeted or not. If different calls have different targeting context, then the bahavior will be like @jimmyca15 mentioned in the comment

See ITargetingContextAccessor

Code implementation:
ref1
ref2
how the sdk determine whether current user/request/device is targeted

@sathishkumarkaliavaradhan
Copy link
Author

@zhiyuanliang-ms Thanks for the reply.

Based on the documentation here - https://learn.microsoft.com/en-us/azure/azure-app-configuration/howto-targetingfilter we thought of AND operation with multiple filters.

how do we add the "requirement_type": "All" in case of multiple filters? when this feature got released?

As I have mentioned in my previous post we are using the Feature flag in our WPF application.
When the app asks first time the feature flag value returnes true then app restarts then asks for the feature flag value again but second time there is no internet then what would be the feature flag value? does the SDK store the feature flag configuration locally when It got downloaded last time?

We also have noticed the feature flag result is flipping between (true/false) based the this configuration below

"clientFilters": [ { "name": "DeviceFilter", "parameters": { "AppVersion": "5.5.0.0" } }, { "name": "Microsoft.Targeting", "parameters": { "Audience": { "Users": [], "Groups": [], "DefaultRolloutPercentage": 50 } } } ],

Since you have mentioned as one condition is true then result is true so in our case first condition is true always. but still we see that result is not 100% true, 10% of the calls are flipping between true/false. we pass only target context which has app version evaluation. did you experience this problem / what would be the wrong in our configuration?

Thanks again for the reply and documentation links.

@zhiyuanliang-ms
Copy link
Contributor

how do we add the "requirement_type": "All" in case of multiple filters? when this feature got released?

It was released in 2.6.0. release note The example in the release has been out of date. Now we have adapted to Microsoft Feature Management schema.

For how "requirement_type" works, I think this doc explains it well.

To configure it on the Azure portal: you can click this:
Image

By default, the requirement_type is Any. If you click it, you can go to Advanced Edit panel of the feature flag, you will find

Image

@zhiyuanliang-ms
Copy link
Contributor

When the app asks first time the feature flag value returnes true then app restarts then asks for the feature flag value again but second time there is no internet then what would be the feature flag value? does the SDK store the feature flag configuration locally when It got downloaded last time?

Yes.
I am assuming you are using our configuration provider library, the .NET provider will load all selected key-values into local configuration. Unless you call our Refresh api, it will use the cached configuration. For your scenario, I am assuming you won't call refresh.

We provide two client libraries: 1. configuration provider 2. feature management
Configuration provider is responsible for load key-value & feature flags from App Config Service.
Feature Management will consume the feature flags loaded by the configuration provider. For more information, please go to doc

@zhiyuanliang-ms
Copy link
Contributor

zhiyuanliang-ms commented Feb 3, 2025

We also have noticed the feature flag result is flipping between (true/false) based the this configuration below

"clientFilters": [ { "name": "DeviceFilter", "parameters": { "AppVersion": "5.5.0.0" } }, { "name": "Microsoft.Targeting", "parameters": { "Audience": { "Users": [], "Groups": [], "DefaultRolloutPercentage": 50 } } } ],

Since you have mentioned as one condition is true then result is true so in our case first condition is true always. but still we see that result is not 100% true, 10% of the calls are flipping between true/false. we pass only target context which has app version evaluation. did you experience this problem / what would be the wrong in our configuration?

Can you provide the full configuration of the feature flag? Are you sure about that the DeviceFilter is always true and you didn't set requirement_type to All?

Could you create a simple example in a github repo or provide some code snippet to let me reproduce the issue?

@sathishkumarkaliavaradhan
Copy link
Author

how do we add the "requirement_type": "All" in case of multiple filters? when this feature got released?

It was released in 2.6.0. release note The example in the release has been out of date. Now we have adapted to Microsoft Feature Management schema.

For how "requirement_type" works, I think this doc explains it well.

To configure it on the Azure portal: you can click this: Image

By default, the requirement_type is Any. If you click it, you can go to Advanced Edit panel of the feature flag, you will find

Image

@zhiyuanliang-ms We have our feature flag configuration likes below

clientFilters": [
        {
          "name": "DeviceFilter",
          "parameters": {
            "AppVersion": "5.5.0.0"
          }
        },
        {
          "name": "Microsoft.Targeting",
          "parameters": {
            "Audience": {
              "Users": [],
              "Groups": [],
              "DefaultRolloutPercentage": 50
            }
          }
        }
      ]

which doesn't have requirement_type property at all, I am not sure how to configure it

@sathishkumarkaliavaradhan
Copy link
Author

We also have noticed the feature flag result is flipping between (true/false) based the this configuration below
"clientFilters": [ { "name": "DeviceFilter", "parameters": { "AppVersion": "5.5.0.0" } }, { "name": "Microsoft.Targeting", "parameters": { "Audience": { "Users": [], "Groups": [], "DefaultRolloutPercentage": 50 } } } ],
Since you have mentioned as one condition is true then result is true so in our case first condition is true always. but still we see that result is not 100% true, 10% of the calls are flipping between true/false. we pass only target context which has app version evaluation. did you experience this problem / what would be the wrong in our configuration?

Can you provide the full configuration of the feature flag? Are you sure about that the DeviceFilter is always true and you didn't set requirement_type to All?

Could you create a simple example in a github repo or provide some code snippet to let me reproduce the issue?

Yes, we have implemented the app version condition which is making sure our app version is above or equal 5.5.0.0 version which is true. because we have other feature flag with only one condition with DeviceFilter which works fine.

@sathishkumarkaliavaradhan
Copy link
Author

When the app asks first time the feature flag value returnes true then app restarts then asks for the feature flag value again but second time there is no internet then what would be the feature flag value? does the SDK store the feature flag configuration locally when It got downloaded last time?

Yes. I am assuming you are using our configuration provider library, the .NET provider will load all selected key-values into local configuration. Unless you call our Refresh api, it will use the cached configuration. For your scenario, I am assuming you won't call refresh.

We provide two client libraries: 1. configuration provider 2. feature management Configuration provider is responsible for load key-value & feature flags from App Config Service. Feature Management will consume the feature flags loaded by the configuration provider. For more information, please go to doc

Yes, we are using the both library AzureAppConfiguration (6.0.0) and feature management (2.5.1). since it's WPF desktop application we don't have request middleware hooked up like ASP.NET Core WebAPI, we are calling the refresher every time before evaluation.

await this.configurationRefresher.TryRefreshAsync().ConfigureAwait(false);
bool remoteFeatureValue = await this.featuremanager.IsEnabledAsync(featureId, DeviceContext).ConfigureAwait(false);
    

Production we are not using the configuration from locally, and we set the cacheexpriationInterval

 configurationBuilder.AddAzureAppConfiguration(options =>
 {
     // To connect with feature flag CDN edge.
     options.Connect(this.connectionString);
     options.UseFeatureFlags(config => config.CacheExpirationInterval = this.Configuration.ConfigurationRefreshInterval);
     this.configurationRefresher = options.GetRefresher();
 }, true);

Please let us know if you see any issue with our configuration.

@rossgrambo
Copy link
Contributor

Requirement Type was added in 2.6.0. You'll need to upgrade to take advantage of it.

In 2.6.0, local schema definition would look like:

"FeatureW": {
    "RequirementType": "All",
    "EnabledFor": []
}

When using the server (like in your production scenario), you'll also need to update AzureAppConfiguration to 7.0.0 or higher as well. Versions before 7 did not persist requirement type.

Not sure your situation, but I'd recommend updating fully to our latest FeatureManagement 4.0.0 and AzureAppConfiguration 8.0.0 if possible.

@zhiyuanliang-ms
Copy link
Contributor

Hi, @sathishkumarkaliavaradhan

Not sure your situation, but I'd recommend updating fully to our latest FeatureManagement 4.0.0 and AzureAppConfiguration 8.0.0 if possible.

As @rossgrambo mentioned, you should upgrade to our latest client libraries.

BTW, can you also share the code snippet about how you register/add feature management and feature filter? Did you have ITargetingContextAccessor?
Besides, can share what DeviceContext looks like? Does it implement ITargetingContext interface? This is interesting, because in web app, we assume that targeting context should be accessed in ambient way.

However, I notice that you are passing DeviceContext directly to IsEnabled call. In this way, it is a different contextual case.

@jimmyca15

@sathishkumarkaliavaradhan
Copy link
Author

Thanks @rossgrambo @jimmyca15 @zhiyuanliang-ms for your reply and sorry for the delay.

Please find the attached code snippet of our code.

AzureFFSampleApp.zip

For this sample application, I used the latest FeatureManagement 4.0.0 and AzureAppConfiguration 8.0.0.

Because of await this.configurationRefresher.TryRefreshAsync().ConfigureAwait(false); it's always calling the API to get the latest configuration and executing the evaluation even though I set the cache expiration interval and notice the time delay for each feature flag evaluation calls.

We would like to use the multiple condition e.g percentage rollout and app version / any other combinations.

Feel free to change the code if required.

@sathishkumarkaliavaradhan
Copy link
Author

Requirement Type was added in 2.6.0. You'll need to upgrade to take advantage of it.

In 2.6.0, local schema definition would look like:

"FeatureW": {
"RequirementType": "All",
"EnabledFor": []
}
When using the server (like in your production scenario), you'll also need to update AzureAppConfiguration to 7.0.0 or higher as well. Versions before 7 did not persist requirement type.

Not sure your situation, but I'd recommend updating fully to our latest FeatureManagement 4.0.0 and AzureAppConfiguration 8.0.0 if possible.

As I mentioned earlier our client calls the CDN endpoint to fetch the Feature flag configuration.

As per your recommendation we clicked the checkbox "Require all above feature filter to be enabled" in Azure Portal but still we didn't get the requirement_type=All property in our CDN configuration and noticed it's not shown advanced edit

I am not sure do we have to upgrade anything on the Azure portal to use the requirement_type=All feature?

@sathishkumarkaliavaradhan
Copy link
Author

Hi @rossgrambo @jimmyca15 @zhiyuanliang-ms , hope you all are doing good. We are kind of struck with above problem.

As per your recommendation we clicked the checkbox "Require all above feature filter to be enabled" in Azure Portal but still we didn't get the requirement_type=All property in our CDN configuration and notice that it's shown in advanced edit view.

We are calling the App configuration from Azure Functions, and CDN calls the Azure Function periodically and our App configuration client calls the CDN configuration from our WPF app client.

This architecture was recommended by Microsoft during our initial discussion of using the Azure App configuration in million of our desktop clients.

I have also attached the sample console application, with exact configuration and upgraded the nuget package FeatureManagement 4.0.0 and AzureAppConfiguration 8.0.0.

I have also raised the azure support ticket for the same issue as well.

@zhiyuanliang-ms
Copy link
Contributor

zhiyuanliang-ms commented Mar 3, 2025

Hi, @sathishkumarkaliavaradhan Sorry for the late response. So much info here. Let me digest them one by one.

Because of await this.configurationRefresher.TryRefreshAsync().ConfigureAwait(false); it's always calling the API to get the latest configuration and executing the evaluation even though I set the cache expiration interval and notice the time delay for each feature flag evaluation calls.

It seems like we have a bug in this line @amerjusupovic @samsadsam Track in #632

Sorry for the inconvenience! Thank you for bring this out!!! This is a bad one. We will fix it as soon as possible.
Could you try to downgrade to provider v7.x. and check whether the refresh operation should be no-op before refresh interval is expired?

---------------- Updated -----------------
But this bug seems to be introduced in 8.1.0. Version 8.0.0 should be fine. The refresh operation will be aborted in this line Could you double check the package version you are using.
I notice there is a slight delay even in 8.0.0, I guess this is because the await. If you cannot stand with the time delay, you can remove the await before `TryRefreshAsync·, like what we do in this example

@zhiyuanliang-ms
Copy link
Contributor

zhiyuanliang-ms commented Mar 3, 2025

Hi, @sathishkumarkaliavaradhan I modified your example application to make everything work.

The major change I did:

  1. IgnoreMissingFeatureFilters should be set to false when requirement_type is All.
  2. DeviceContext should also implement ITargetingContext. The ContextualTargetingFilter can only consume ITargetingContext code doc
  3. Updated DeviceFilter. Now it will return true if the AppVersion in context matches the AppVersion you configured in the filter parameter.
  4. Updated Program.cs file to demostrate how DefaultRolloutPercentage and requirement_type=All work.

You should get the following result when running the application:

Image

Here is the code:
fix.zip

This is the feature flag I have in my App Configuration store.
Image

@zhiyuanliang-ms
Copy link
Contributor

@sathishkumarkaliavaradhan BTW, if my understanding is correct, you are using Azure App Configuration as CDN, right? Will you really put a connection string of your App Configuration store in your client application? If this is true, please not do that. 1. put secret in client is not safe 2. Currently, App Config is not designed for edge delivery scenario, even if we have premium tier which will never give you throttling response. If you are not using premium tier, this is our quota:

Image

Our CDN solution is still work in progress. In about April or May, we will present our CDN solution which will be safe and reliable.

@sathishkumarkaliavaradhan
Copy link
Author

Thank you so much @zhiyuanliang-ms . I really appreciate your help.

We are not Azure App configuration as CDN instead

App Configuration -> Azure function using the DefaultCrdentials -> Azure CDN which calls the Azure Function using function code -> App Configuration client calls Azure CDN endpoint to get the configuration using the CDN endpoint without authorization. we are not at all hardcoded the secrets in our client application.

Edge delivery setup for Azure AppConfiguration (1).docx

Edge delivery architecture provider by Microsoft because our case we have millions of desktop client for which App configuration doesn't support quota means 30,000 per hour is too less for our clients.

It works fine, except the latest FF scenario of multiple condition with requirement_type": "All" where the CDN response doesn't contains the requirement_type": "All" value but we have it in our advance edit view.

@zhiyuanliang-ms
Copy link
Contributor

where the CDN response doesn't contains the requirement_type": "All" value but we have it in our advance edit view

This sounds weird. Can you get the requirement_type from app config by using .NET provider locally or using it in Azure Function?

@sathishkumarkaliavaradhan
Copy link
Author

Thanks @zhiyuanliang-ms for your response again.

I suspect that in our Azure function, we are using the Azure.Data.AppConfiguration version 1.2.0 and I see the latest version 1.5.0. do we know which version of Azure.Data.AppConfiguration SDK supports the requirement_type": "All" feature?

@zhiyuanliang-ms
Copy link
Contributor

Hi, @sathishkumarkaliavaradhan

we are using the Azure.Data.AppConfiguration version 1.2.0

If that is the case, then it can explain why you cannot get requirement_type. This is a known issue. I believe the SDK fixed that bug in 1.3.0-beta.3, see the release note

Could you try to use the latest version of Azure.Data.AppConfiguration. Or you can use our latest bersion of configuration provider library: Microsoft.Extensions.Configuration.AzureAppConfiguration which has dependency on Azure.Data.AppConfiguration (>= 1.4.1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

4 participants