microsoft / FeatureManagement-Dotnet

Microsoft.FeatureManagement provides standardized APIs for enabling feature flags within applications. Utilize this library to secure a consistent experience when developing applications that use patterns such as beta access, rollout, dark deployments, and more.
MIT License
1.06k stars 115 forks source link

The StatusOverride doesn't work #393

Closed zhenlan closed 8 months ago

zhenlan commented 8 months ago

Hi, the StatusOverride doesn't work for me. May I get some help?

Here is my feature flag

{
    "id": "Greeting",
    "description": "",
    "enabled": true,
    "variants": [
        {
            "name": "Off",
            "configuration_value": "false",
            "StatusOverride": "Disabled"
        },
        {
            "name": "On",
            "configuration_value": "true",
            "StatusOverride": "Enabled"
        }
    ],
    "allocation": {
        "percentile": [
            {
                "variant": "Off",
                "from": 0,
                "to": 80
            },
            {
                "variant": "On",
                "from": 80,
                "to": 100
            }
        ],
        "default_when_enabled": "Off",
        "default_when_disabled": "Off"
    },
    "telemetry": {
        "enabled": true
    }
}

Here is my code for a razor page

public async void OnGet()
{
    Variant variant = await _featureManager.GetVariantAsync("Greeting", default);
    ShowGreeting = variant.Configuration.Get<bool>();

    // BUG: StatusOverride in the feature flag doesn't work. The following code will
    //      always return true even when the "Off" variant is assigned.
    bool showGreeting2 = await _featureManager.IsEnabledAsync("Greeting", default);
}

When "Off" variant is assigned, the IsEnabledAsync is expected to return false, but I always got true from it. This is their values under the debugger image

Here are my project dependencies

  <ItemGroup>
    <PackageReference Include="Azure.Identity" Version="1.10.4" />
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.22.0" />
    <PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="8.0.0-preview" />
    <PackageReference Include="Microsoft.FeatureManagement.AspNetCore" Version="4.0.0-preview2" />
    <PackageReference Include="Microsoft.FeatureManagement.Telemetry.ApplicationInsights" Version="4.0.0-preview2" />
    <PackageReference Include="Microsoft.FeatureManagement.Telemetry.ApplicationInsights.AspNetCore" Version="4.0.0-preview2" />
  </ItemGroup>

Do I miss anything?

zhiyuanliang-ms commented 8 months ago

@zhenlan I assume you are using Microsoft Feature Flag schema. I don't know whether this is the reason, but I found you used "StatusOverride" instead of "status_override".

I think this is because .NET provider/ feature management lib cannot find the StatusOverride field.

zhiyuanliang-ms commented 8 months ago

@zhenlan I tested this on my side with the following feature flag configuration:

{
  "FeatureManagement": {
    "Greeting": {
      "Variants": [
        {
          "Name": "Off",
          "ConfigurationValue": "false",
          "StatusOverride": "Disabled"
        },
        {
          "Name": "On",
          "ConfigurationValue": "true",
          "StatusOverride": "Enabled"
        }
      ],
      "Allocation": {
        "Percentile": [
          {
            "Variant": "Off",
            "From": 0,
            "To": 80
          },
          {
            "Variant": "On",
            "From": 80,
            "To": 100
          }
        ],
        "DefaultWhenEnabled": "Off",
        "DefaultWhenDisabled": "Off"
      },
      "EnabledFor": [
        {
          "Name": "AlwaysOn"
        }
      ]
    }
  }
}

and

{
  "feature_management": {
    "feature_flags": [
      {
        "id": "Greeting",
        "description": "",
        "enabled": true,
        "variants": [
          {
            "name": "Off",
            "configuration_value": "false",
            "status_override": "Disabled"
          },
          {
            "name": "On",
            "configuration_value": "true",
            "status_override": "Enabled"
          }
        ],
        "allocation": {
          "percentile": [
            {
              "variant": "Off",
              "from": 0,
              "to": 80
            },
            {
              "variant": "On",
              "from": 80,
              "to": 100
            }
          ],
          "default_when_enabled": "Off",
          "default_when_disabled": "Off"
        },
        "telemetry": {
          "enabled": true
        }
      }
    ]
  }
}

Both gave me false for showGreeting2.

zhenlan commented 8 months ago

@zhenlan I assume you are using Microsoft Feature Flag schema. I don't know whether this is the reason, but I found you used "StatusOverride" instead of "status_override

No, I loaded the feature flag from AppConfig. But you are right, this does the trick.

This is so confusing. Maybe we should rethink the support for Pascal casing of new properties in .NET.

jimmyca15 commented 8 months ago

Maybe we should rethink the support for Pascal casing of new properties in .NET.

Do you mean to consider no longer adding new properties to the .NET feature flag schema?

zhenlan commented 8 months ago

Maybe we should rethink the support for Pascal casing of new properties in .NET.

Do you mean to consider no longer adding new properties to the .NET feature flag schema?

Correct. The alternative is to use the snake casing there too, but it may look weird.

jimmyca15 commented 8 months ago

The alternative is to use the snake casing there too, but it may look weird.

Agree, if anything it's just that we deprecate the .NET flag schema in a major version bump.

zhenlan commented 8 months ago

@zhiyuanliang-ms if we reached consensus that we will not support new properties in the old schema, we should open a new issue (given this one is closed) to clean them up.

zhiyuanliang-ms commented 8 months ago

@zhenlan Agree.