Skip to content

Commit

Permalink
Merge branch 'rossgrambo/cache-filter-parameters' of https://github.c…
Browse files Browse the repository at this point in the history
…om/microsoft/FeatureManagement-Dotnet into rossgrambo/cache-filter-parameters
  • Loading branch information
rossgrambo committed May 13, 2023
2 parents 576b762 + c1a7240 commit 541bfc0
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 16 deletions.
105 changes: 93 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ASP.NET Core Feature Flags
# .NET Feature Management

Feature flags provide a way for ASP.NET Core applications to turn features on or off dynamically. Developers can use feature flags in simple use cases like conditional statements to more advanced scenarios like conditionally adding routes or MVC filters. Feature flags build on top of the .NET Core configuration system. Any .NET Core configuration provider is capable of acting as the back-bone for feature flags.
Feature flags provide a way for .NET and ASP.NET Core applications to turn features on or off dynamically. Developers can use feature flags in simple use cases like conditional statements to more advanced scenarios like conditionally adding routes or MVC filters. Feature flags build on top of the .NET Core configuration system. Any .NET Core configuration provider is capable of acting as the back-bone for feature flags.

Here are some of the benefits of using this library:

Expand All @@ -20,15 +20,26 @@ Here are some of the benefits of using this library:

**API Reference**: https://go.microsoft.com/fwlink/?linkid=2091700

### Feature Flags
## Index
* [Feature Flags](#feature-flags)
* [Feature Filters](#feature-filters)
* [Feature Flag Declaration](#feature-flag-declaration)
* [ASP.NET Core Integration](#ASPNET-Core-Integration)
* [Built-in Feature Filters](#built-in-Feature-Filters)
* [Targeting](#targeting)
* [Targeting Exclusion](#targeting-exclusion)
* [Caching](#caching)
* [Custom Feature Providers](#custom-feature-providers)

## Feature Flags
Feature flags are composed of two parts, a name and a list of feature-filters that are used to turn the feature on.

### Feature Filters
Feature filters define a scenario for when a feature should be enabled. When a feature is evaluated for whether it is on or off, its list of feature-filters are traversed until one of the filters decides the feature should be enabled. At this point the feature is considered enabled and traversal through the feature filters stops. If no feature filter indicates that the feature should be enabled, then it will be considered disabled.

As an example, a Microsoft Edge browser feature filter could be designed. This feature filter would activate any features it is attached to as long as an HTTP request is coming from Microsoft Edge.

## Registration
### Feature Flag Configuration

The .NET Core configuration system is used to determine the state of feature flags. The foundation of this system is `IConfiguration`. Any provider for IConfiguration can be used as the feature state provider for the feature flag library. This enables scenarios ranging from appsettings.json to Azure App Configuration and more.

Expand Down Expand Up @@ -71,7 +82,7 @@ The feature management library supports appsettings.json as a feature flag sourc
}
```

The `FeatureManagement` section of the json document is used by convention to load feature flag settings. In the section above, we see that we have provided three different features. Features define their feature filters using the `EnabledFor` property. In the feature filters for `FeatureT` we see `AlwaysOn`. This feature filter is built-in and if specified will always enable the feature. The `AlwaysOn` feature filter does not require any configuration so it only has the _Name_ property. `FeatureU` has no filters in its `EnabledFor` property and thus will never be enabled. Any functionality that relies on this feature being enabled will not be accessible as long as the feature filters remain empty. However, as soon as a feature filter is added that enables the feature it can begin working. `FeatureV` specifies a feature filter named `TimeWindow`. This is an example of a configurable feature filter. We can see in the example that the filter has a parameter's property. This is used to configure the filter. In this case, the start and end times for the feature to be active are configured.
The `FeatureManagement` section of the json document is used by convention to load feature flag settings. In the section above, we see that we have provided three different features. Features define their feature filters using the `EnabledFor` property. In the feature filters for `FeatureT` we see `AlwaysOn`. This feature filter is built-in and if specified will always enable the feature. The `AlwaysOn` feature filter does not require any configuration so it only has the `Name` property. `FeatureU` has no filters in its `EnabledFor` property and thus will never be enabled. Any functionality that relies on this feature being enabled will not be accessible as long as the feature filters remain empty. However, as soon as a feature filter is added that enables the feature it can begin working. `FeatureV` specifies a feature filter named `TimeWindow`. This is an example of a configurable feature filter. We can see in the example that the filter has a `Parameters` property. This is used to configure the filter. In this case, the start and end times for the feature to be active are configured.

### On/Off Declaration

Expand All @@ -91,6 +102,39 @@ The following snippet demonstrates an alternative way to define a feature that c
}
}
```

### RequirementType

The `RequirementType` property of a feature flag is used to determine if the filters should use `Any` or `All` logic when evaluating the state of a feature. If `RequirementType` is not specified, the default value is `Any`.

* `Any` means only 1 filter needs to evaluate to true for the feature to be enabled.
* `All` means every filter needs to evaluate to true for the feature to be enabled.

A `RequirementType` of `All` changes the traversal. First, if there are no filters, the feature will be disabled. Then, the feature-filters are traversed until one of the filters decides that the feature should be disabled. If no filter indicates that the feature should be disabled, then it will be considered enabled.

```
"FeatureW": {
"RequirementType": "All",
"EnabledFor": [
{
"Name": "TimeWindow",
"Parameters": {
"Start": "Mon, 01 May 2023 13:59:59 GMT",
"End": "Sat, 01 July 2023 00:00:00 GMT"
}
},
{
"Name": "Percentage",
"Parameters": {
"Value": "50"
}
}
]
}
```

In the above example, `FeatureW` specifies a `RequirementType` of `All`, meaning all of it's filters must evaluate to true for the feature to be enabled. In this case, the feature will be enabled for 50% of users during the specified time window.

### Referencing

To make it easier to reference these feature flags in code, we recommend to define feature flag variables like below.
Expand Down Expand Up @@ -161,6 +205,9 @@ public class HomeController : Controller
}
```

## ASP.NET Core Integration
The feature management library provides functionality in ASP.NET Core and MVC to enable common feature flag scenarios in web applications. These capabilities are available by referencing the [Microsoft.FeatureManagement.AspNetCore](https://www.nuget.org/packages/Microsoft.FeatureManagement.AspNetCore/) NuGet package.

### Controllers and Actions
MVC controller and actions can require that a given feature, or one of any list of features, be enabled in order to execute. This can be done by using a `FeatureGateAttribute`, which can be found in the `Microsoft.FeatureManagement.Mvc` namespace.

Expand Down Expand Up @@ -440,7 +487,7 @@ This filter provides the capability to enable a feature based on a time window.

#### Microsoft.Targeting

This filter provides the capability to enable a feature for a target audience. An in-depth explanation of targeting is explained in the [targeting](./README.md#Targeting) section below. The filter parameters include an audience object which describes users, groups, and a default percentage of the user base that should have access to the feature. Each group object that is listed in the target audience must also specify what percentage of the group's members should have access. If a user is specified in the users section directly, or if the user is in the included percentage of any of the group rollouts, or if the user falls into the default rollout percentage then that user will have the feature enabled.
This filter provides the capability to enable a feature for a target audience. An in-depth explanation of targeting is explained in the [targeting](./README.md#Targeting) section below. The filter parameters include an audience object which describes users, groups, excluded users/groups, and a default percentage of the user base that should have access to the feature. Each group object that is listed in the target audience must also specify what percentage of the group's members should have access. If a user is specified in the exclusion section, either directly or if the user is in an excluded group, the feature will be disabled. Otherwise, if a user is specified in the users section directly, or if the user is in the included percentage of any of the group rollouts, or if the user falls into the default rollout percentage then that user will have the feature enabled.

``` JavaScript
"EnhancedPipeline": {
Expand All @@ -463,7 +510,15 @@ This filter provides the capability to enable a feature for a target audience. A
"RolloutPercentage": 50
}
],
"DefaultRolloutPercentage": 20
"DefaultRolloutPercentage": 20,
"Exclusion": {
"Users": [
"Ross"
],
"Groups": [
"Ring2"
]
}
}
}
}
Expand All @@ -477,7 +532,7 @@ All of the built-in feature filter alias' are in the 'Microsoft' feature filter

## Targeting

Targeting is a feature management strategy that enables developers to progressively roll out new features to their user base. The strategy is built on the concept of targeting a set of users known as the target _audience_. An audience is made up of specific users, groups, and a designated percentage of the entire user base. The groups that are included in the audience can be broken down further into percentages of their total members.
Targeting is a feature management strategy that enables developers to progressively roll out new features to their user base. The strategy is built on the concept of targeting a set of users known as the target _audience_. An audience is made up of specific users, groups, excluded users/groups, and a designated percentage of the entire user base. The groups that are included in the audience can be broken down further into percentages of their total members.

The following steps demonstrate an example of a progressive rollout for a new 'Beta' feature:

Expand All @@ -490,7 +545,7 @@ The following steps demonstrate an example of a progressive rollout for a new 'B

This strategy for rolling out a feature is built in to the library through the included [Microsoft.Targeting](./README.md#MicrosoftTargeting) feature filter.

## Targeting in a Web Application
### Targeting in a Web Application

An example web application that uses the targeting feature filter is available in the [FeatureFlagDemo](./examples/FeatureFlagDemo) example project.

Expand All @@ -506,13 +561,13 @@ services.AddFeatureManagement();
```

### ITargetingContextAccessor
#### ITargetingContextAccessor

To use the `TargetingFilter` in a web application an implementation of `ITargetingContextAccessor` is required. This is because when a targeting evaluation is being performed information such as what user is currently being evaluated is needed. This information is known as the targeting context. Different web applications may extract this information from different places. Some common examples of where an application may pull the targeting context are the request's HTTP context or a database.

An example that extracts targeting context information from the application's HTTP context is included in the [FeatureFlagDemo](./examples/FeatureFlagDemo/HttpContextTargetingContextAccessor.cs) example project. This method relies on the use of `IHttpContextAccessor` which is discussed [here](./README.md#Using-HttpContext).

## Targeting in a Console Application
### Targeting in a Console Application

The targeting filter relies on a targeting context to evaluate whether a feature should be turned on. This targeting context contains information such as what user is currently being evaluated, and what groups the user in. In console applications there is typically no ambient context available to flow this information in to the targeting filter, thus it must be passed directly when `FeatureManager.IsEnabledAsync` is called. This is supported through the use of the `ContextualTargetingFilter`. Applications that need to float the targeting context into the feature manager should use this instead of the `TargetingFilter.`

Expand Down Expand Up @@ -540,7 +595,7 @@ The `ContextualTargetingFilter` still uses the feature filter alias [Microsoft.T

An example that uses the `ContextualTargetingFilter` in a console application is available in the [TargetingConsoleApp](./examples/TargetingConsoleApp) example project.

## Targeting Evaluation Options
### Targeting Evaluation Options

Options are available to customize how targeting evaluation is performed across all features. These options can be configured when setting up feature management.

Expand All @@ -551,6 +606,32 @@ services.Configure<TargetingEvaluationOptions>(options =>
});
```

### Targeting Exclusion

When defining an Audience, users and groups can be excluded from the audience. This is useful when a feature is being rolled out to a group of users, but a few users or groups need to be excluded from the rollout. Exclusion is defined by adding a list of users and groups to the `Exclusion` property of the audience.
```
"Audience": {
"Users": [
"Jeff",
"Alicia"
],
"Groups": [
{
"Name": "Ring0",
"RolloutPercentage": 100
}
],
"DefaultRolloutPercentage": 0
"Exclusion": {
"Users": [
"Mark"
]
}
}
```

In the above example, the feature will be enabled for users named `Jeff` and `Alicia`. It will also be enabled for users in the group named `Ring0`. However, if the user is named `Mark`, the feature will be disabled, regardless if they are in the group `Ring0` or not. Exclusions take priority over the rest of the targeting filter.

## Caching

Feature state is provided by the IConfiguration system. Any caching and dynamic updating is expected to be handled by configuration providers. The feature manager asks IConfiguration for the latest value of a feature's state whenever a feature is checked to be enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
<!-- Official Version -->
<PropertyGroup>
<MajorVersion>2</MajorVersion>
<MinorVersion>5</MinorVersion>
<PatchVersion>1</PatchVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreviewVersion>-preview</PreviewVersion>
</PropertyGroup>

<Import Project="..\..\build\Versioning.props" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
<!-- Official Version -->
<PropertyGroup>
<MajorVersion>2</MajorVersion>
<MinorVersion>5</MinorVersion>
<PatchVersion>1</PatchVersion>
<MinorVersion>6</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreviewVersion>-preview</PreviewVersion>
</PropertyGroup>

<Import Project="..\..\build\Versioning.props" />
Expand Down

0 comments on commit 541bfc0

Please sign in to comment.