diff --git a/README.md b/README.md index 6f6e99c5..bad85412 100644 --- a/README.md +++ b/README.md @@ -58,52 +58,11 @@ The .NET Core configuration system is used to determine the state of feature fla ### Feature Flag Declaration -The feature management library supports appsettings.json as a feature flag source since it is a provider for .NET Core's IConfiguration system. Below we have an example of the format used to set up feature flags in a json file. +The feature management library supports appsettings.json as a feature flag source since it is a provider for .NET Core's IConfiguration system. Feature flags are declared using the [`Microsoft Feature Management schema`](https://github.com/Azure/AppConfiguration/blob/main/docs/FeatureManagement/FeatureManagement.v2.0.0.schema.json). This schema is language agnostic in origin and is supported by all Microsoft feature management libraries. -``` JavaScript -{ - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - - // Define feature flags in a json file - "FeatureManagement": { - "FeatureT": { - "EnabledFor": [ - { - "Name": "AlwaysOn" - } - ] - }, - "FeatureU": { - "EnabledFor": [] - }, - "FeatureV": { - "EnabledFor": [ - { - "Name": "TimeWindow", - "Parameters": { - "Start": "Wed, 01 May 2019 13:59:59 GMT", - "End": "Mon, 01 July 2019 00:00:00 GMT" - } - } - ] - } - } -} -``` - -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. -The detailed schema of the `FeatureManagement` section can be found [here](./schemas/FeatureManagement.Dotnet.v2.0.0.schema.json). +Below we have an example of declaring feature flags in a json file. -**Advanced:** The usage of colon ':' in feature flag names is forbidden. - -#### On/Off Declaration - -The following snippet demonstrates an alternative way to define a feature that can be used for on/off features. ``` JavaScript { "Logging": { @@ -112,74 +71,20 @@ The following snippet demonstrates an alternative way to define a feature that c } }, - // Define feature flags in config file - "FeatureManagement": { - "FeatureT": true, // On feature - "FeatureX": false // Off feature - } -} -``` - -#### 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 one 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. - -``` JavaScript -"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. - -#### Status - -`Status` is an optional property of a feature flag that controls how a flag's enabled state is evaluated. By default, the status of a flag is `Conditional`, meaning that feature filters should be evaluated to determine if the flag is enabled. If the `Status` of a flag is set to `Disabled` then feature filters are not evaluated and the flag is always considered to be disabled. - - -``` JavaScript -"FeatureX": { - "Status": "Disabled", - "EnabledFor": [ - { - "Name": "AlwaysOn" - } - ] -} -``` - -In this example, even though the `AlwaysOn` filter would normally always make the feature enabled, the `Status` property is set to `Disabled`, so this feature will always be disabled. - -#### Microsoft Feature Management Schema - -The feature management library also supports the usage of the [`Microsoft Feature Management schema`](https://github.com/Azure/AppConfiguration/blob/main/docs/FeatureManagement/FeatureManagement.v1.0.0.schema.json) to declare feature flags. This schema is language agnostic in origin and is supported by all Microsoft feature management libraries. - -``` JavaScript -{ + // Define feature flags in a json file "feature_management": { "feature_flags": [ { "id": "FeatureT", + "enabled": false + }, + { + "id": "FeatureU", + "enabled": true, + "conditions": {} + }, + { + "id": "FeatureV", "enabled": true, "conditions": { "client_filters": [ @@ -198,29 +103,35 @@ The feature management library also supports the usage of the [`Microsoft Featur } ``` -**Note:** If the `feature_management` section can be found in the configuration, the `FeatureManagement` section will be ignored. +The `feature_management` section of the json document is used by convention to load feature flag settings. Feature flag objects must be listed in the `feature_flags` array under the `feature_management` section. In the section above, we see that we have provided three different features. A feature flag has `id` and `enabled` properties. The `id` is the name used to identify and reference the feature flag. The `enabled` property specifies the enabled state of the feature flag. A feature is *OFF* if `enabled` is false. If `enabled` is true, then the state of the feature depends on the `conditions`. If there are no `conditions` then the feature is *ON*. If there are `conditions` and they are met then the feature is *ON*. If there are `conditions` and they are not met then the feature is *OFF*. The `conditions` property declares the conditions used to dynamically enabled the feature. Features define their feature filters in the `client_filters` array. `FeatureV` specifies a feature filter named `Microsoft.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. + +#### Requirement Type -#### Microsoft Feature Management Schema +The `requirement_type` property of `conditions` is used to determine if the filters should use `Any` or `All` logic when evaluating the state of a feature. If `requirement_type` is not specified, the default value is `Any`. -The feature management library also supports the usage of the [`Microsoft Feature Management schema`](https://github.com/Azure/AppConfiguration/blob/main/docs/FeatureManagement/FeatureManagement.v1.0.0.schema.json) to declare feature flags. This schema is language agnostic in origin and is supported by all Microsoft feature management libraries. +* `Any` means only one 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 `requirement_type` of `All` changes the traversal. First, if there are no filters, the feature will be disabled. If there are filters, 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. ``` JavaScript { - "feature_management": { - "feature_flags": [ + "id": "FeatureW", + "enabled": true, + "conditions": { + "requirement_type": "All", + "client_filters": [ { - "id": "FeatureT", - "enabled": true, - "conditions": { - "client_filters": [ - { - "name": "Microsoft.TimeWindow", - "parameters": { - "Start": "Mon, 01 May 2023 13:59:59 GMT", - "End": "Sat, 01 July 2023 00:00:00 GMT" - } - } - ] + "name": "Microsoft.TimeWindow", + "parameters": { + "Start": "Mon, 01 May 2023 13:59:59 GMT", + "End": "Sat, 01 Jul 2023 00:00:00 GMT" + } + }, + { + "name": "Microsoft.Percentage", + "parameters": { + "Value": "50" } } ] @@ -228,7 +139,11 @@ The feature management library also supports the usage of the [`Microsoft Featur } ``` -**Note:** If the `feature_management` section can be found in the configuration, the `FeatureManagement` section will be ignored. +In the above example, `FeatureW` specifies a `requirement_type` 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. + +### .NET Feature Management schema + +In previous versions, the primary schema for the feature management library was the [.NET feature management schema](./schemas/FeatureManagement.Dotnet.v1.0.0.schema.json). Starting from v4.0.0, new features including variants and telemetry will not be supported for the .NET feature management schema. ## Consumption @@ -260,9 +175,9 @@ public class Startup } ``` -By default, the feature manager retrieves feature flag configuration from the "FeatureManagement" section of the .NET Core configuration data. If the "FeatureManagement" section does not exist, the configuration will be considered empty. +By default, the feature manager retrieves feature flag configuration from the `feature_management` section of the .NET Core configuration data. If the `feature_management` section does not exist, the configuration will be considered empty. -You can also specify that feature flag configuration should be retrieved from a different configuration section by passing the section to `AddFeatureManagement`. The following example tells the feature manager to read from a different section called "MyFeatureFlags" instead: +**Note:** You can also specify that feature flag configuration should be retrieved from a different configuration section by passing the section to `AddFeatureManagement`. The following example tells the feature manager to read from a different section called "MyFeatureFlags" instead: ``` C# services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags")); @@ -478,10 +393,10 @@ public class BrowserFilter : IFeatureFilter When a feature filter is registered to be used for a feature flag, the alias used in configuration is the name of the feature filter type with the _Filter_ suffix, if any, removed. For example, `MyCriteriaFilter` would be referred to as _MyCriteria_ in configuration. ``` JavaScript -"MyFeature": { - "EnabledFor": [ +"conditions": { + "client_filters": [ { - "Name": "MyCriteria" + "name": "MyCriteria" } ] } @@ -596,11 +511,11 @@ Each of the built-in feature filters have their own parameters. Here is the list This filter provides the capability to enable a feature based on a set percentage. ``` JavaScript -"EnhancedPipeline": { - "EnabledFor": [ +"conditions": { + "client_filters": [ { - "Name": "Microsoft.Percentage", - "Parameters": { + "name": "Microsoft.Percentage", + "parameters": { "Value": 50 } } @@ -613,13 +528,13 @@ This filter provides the capability to enable a feature based on a set percentag This filter provides the capability to enable a feature based on a time window. If only `End` is specified, the feature will be considered on until that time. If only `Start` is specified, the feature will be considered on at all points after that time. ``` JavaScript -"EnhancedPipeline": { - "EnabledFor": [ +"conditions": { + "client_filter": [ { - "Name": "Microsoft.TimeWindow", - "Parameters": { + "name": "Microsoft.TimeWindow", + "parameters": { "Start": "Wed, 01 May 2019 13:59:59 GMT", - "End": "Mon, 01 July 2019 00:00:00 GMT" + "End": "Mon, 01 Jul 2019 00:00:00 GMT" } } ] @@ -631,11 +546,11 @@ This filter provides the capability to enable a feature based on a time window. 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": { - "EnabledFor": [ +"conditions": { + "client_filters": [ { - "Name": "Microsoft.Targeting", - "Parameters": { + "name": "Microsoft.Targeting", + "parameters": { "Audience": { "Users": [ "Jeff", @@ -817,40 +732,37 @@ The variant returned is dependent on the user currently being evaluated, and tha ### Variant Feature Flag Declaration -Compared to normal feature flags, variant feature flags have two additional properties: `Variants` and `Allocation`. The `Variants` property is an array that contains the variants defined for this feature. The `Allocation` property defines how these variants should be allocated for the feature. Just like declaring normal feature flags, you can set up variant feature flags in a json file. Here is an example of a variant feature flag. +Compared to normal feature flags, variant feature flags have two additional properties: `variants` and `allocation`. The `variants` property is an array that contains the variants defined for this feature. The `allocation` property defines how these variants should be allocated for the feature. Just like declaring normal feature flags, you can set up variant feature flags in a json file. Here is an example of a variant feature flag. ``` javascript { - "FeatureManagement": - { - "MyVariantFeatureFlag": - { - "Allocation": { - "DefaultWhenEnabled": "Small", - "Group": [ - { - "Variant": "Big", - "Groups": [ - "Ring1" - ] - } + "feature_management": { + "feature_flags": [ + { + "id": "MyVariantFeatureFlag", + "enabled": true, + "allocation": { + "default_when_enabled": "Small", + "group": [ + { + "variant": "Big", + "groups": [ + "Ring1" + ] + } + ] + }, + "variants": [ + { + "name": "Big" + }, + { + "name": "Small" + } ] - }, - "Variants": [ - { - "Name": "Big" - }, - { - "Name": "Small" - } - ], - "EnabledFor": [ - { - "Name": "AlwaysOn" - } - ] - } + } + ] } } @@ -860,35 +772,31 @@ For more details about how to configure variant feature flags, please see [here] #### Defining Variants -Each variant has two properties: a name and a configuration. The name is used to refer to a specific variant, and the configuration is the value of that variant. The configuration can be set using either the `ConfigurationReference` or `ConfigurationValue` properties. `ConfigurationReference` is a string path that references a section of the current configuration that contains the feature flag declaration. `ConfigurationValue` is an inline configuration that can be a string, number, boolean, or configuration object. If both are specified, `ConfigurationValue` is used. If neither are specified, the returned variant's `Configuration` property will be null. +Each variant has two properties: a name and a configuration. The name is used to refer to a specific variant, and the configuration is the value of that variant. The configuration can be set using either the `configuration_reference` or `configuration_value` properties. `configuration_reference` is a string path that references a section of the current configuration that contains the feature flag declaration. `configuration_value` is an inline configuration that can be a string, number, boolean, or configuration object. If both are specified, `configuration_value` is used. If neither are specified, the returned variant's `Configuration` property will be null. -A list of all possible variants is defined for each feature under the `Variants` property. +A list of all possible variants is defined for each feature under the `variants` property. ``` javascript { - "FeatureManagement": - { - "MyVariantFeatureFlag": - { - "Variants": [ - { - "Name": "Big", - "ConfigurationReference": "ShoppingCart:Big" - }, - { - "Name": "Small", - "ConfigurationValue": { - "Size": 300 - } - } - ], - "EnabledFor": [ - { - "Name": "AlwaysOn" - } - ] - } - } + "feature_management": { + "feature_flags": [ + { + "id": "MyVariantFeatureFlag", + "variants": [ + { + "name": "Big", + "configuration_reference": "ShoppingCart:Big" + }, + { + "name": "Small", + "configuration_value": { + "Size": 300 + } + } + ] + } + ] + }, "ShoppingCart": { "Big": { @@ -905,63 +813,63 @@ A list of all possible variants is defined for each feature under the `Variants` #### Allocating Variants -The process of allocating a feature's variants is determined by the `Allocation` property of the feature. +The process of allocating a feature's variants is determined by the `allocation` property of the feature. ``` javascript -"Allocation": { - "DefaultWhenEnabled": "Small", - "DefaultWhenDisabled": "Small", - "User": [ +"allocation": { + "default_when_enabled": "Small", + "default_when_disabled": "Small", + "user": [ { - "Variant": "Big", - "Users": [ + "variant": "Big", + "users": [ "Marsha" ] } ], - "Group": [ + "group": [ { - "Variant": "Big", - "Groups": [ + "variant": "Big", + "groups": [ "Ring1" ] } ], - "Percentile": [ + "percentile": [ { - "Variant": "Big", - "From": 0, - "To": 10 + "variant": "Big", + "from": 0, + "to": 10 } ], - "Seed": "13973240" + "seed": "13973240" }, -"Variants": [ +"variants": [ { - "Name": "Big", - "ConfigurationReference": "ShoppingCart:Big" + "name": "Big", + "configuration_reference": "ShoppingCart:Big" }, { - "Name": "Small", - "ConfigurationValue": "300px" + "name": "Small", + "configuration_value": "300px" } ] ``` -The `Allocation` setting of a feature flag has the following properties: +The `allocation` setting of a feature flag has the following properties: | Property | Description | | ---------------- | ---------------- | -| `DefaultWhenDisabled` | Specifies which variant should be used when a variant is requested while the feature is considered disabled. | -| `DefaultWhenEnabled` | Specifies which variant should be used when a variant is requested while the feature is considered enabled and no other variant was assigned to the user. | -| `User` | Specifies a variant and a list of users to whom that variant should be assigned. | -| `Group` | Specifies a variant and a list of groups. The variant will be assigned if the user is in at least one of the groups. | -| `Percentile` | Specifies a variant and a percentage range the user's calculated percentage has to fit into for that variant to be assigned. | -| `Seed` | The value which percentage calculations for `Percentile` are based on. The percentage calculation for a specific user will be the same across all features if the same `Seed` value is used. If no `Seed` is specified, then a default seed is created based on the feature name. | +| `default_when_disabled` | Specifies which variant should be used when a variant is requested while the feature is considered disabled. | +| `default_when_enabled` | Specifies which variant should be used when a variant is requested while the feature is considered enabled and no other variant was assigned to the user. | +| `user` | Specifies a variant and a list of users to whom that variant should be assigned. | +| `group` | Specifies a variant and a list of groups. The variant will be assigned if the user is in at least one of the groups. | +| `percentile` | Specifies a variant and a percentage range the user's calculated percentage has to fit into for that variant to be assigned. | +| `seed` | The value which percentage calculations for `percentile` are based on. The percentage calculation for a specific user will be the same across all features if the same `seed` value is used. If no `seed` is specified, then a default seed is created based on the feature name. | -In the above example, if the feature is not enabled, the feature manager will assign the variant marked as `DefaultWhenDisabled` to the current user, which is `Small` in this case. +In the above example, if the feature is not enabled, the feature manager will assign the variant marked as `default_when_disabled` to the current user, which is `Small` in this case. -If the feature is enabled, the feature manager will check the `User`, `Group`, and `Percentile` allocations in that order to assign a variant. For this particular example, if the user being evaluated is named `Marsha`, in the group named `Ring1`, or the user happens to fall between the 0 and 10th percentile, then the specified variant is assigned to the user. In this case, all of these would return the `Big` variant. If none of these allocations match, the user is assigned the `DefaultWhenEnabled` variant, which is `Small`. +If the feature is enabled, the feature manager will check the `user`, `group`, and `percentile` allocations in that order to assign a variant. For this particular example, if the user being evaluated is named `Marsha`, in the group named `Ring1`, or the user happens to fall between the 0 and 10th percentile, then the specified variant is assigned to the user. In this case, all of these would return the `Big` variant. If none of these allocations match, the user is assigned the `default_when_enabled` variant, which is `Small`. Allocation logic is similar to the [Microsoft.Targeting](./README.md#MicrosoftTargeting) feature filter, but there are some parameters that are present in targeting that aren't in allocation, and vice versa. The outcomes of targeting and allocation are not related. @@ -969,39 +877,38 @@ Allocation logic is similar to the [Microsoft.Targeting](./README.md#MicrosoftTa ### Overriding Enabled State with a Variant -You can use variants to override the enabled state of a feature flag. This gives variants an opportunity to extend the evaluation of a feature flag. If a caller is checking whether a flag that has variants is enabled, the feature manager will check if the variant assigned to the current user is set up to override the result. This is done using the optional variant property `StatusOverride`. By default, this property is set to `None`, which means the variant doesn't affect whether the flag is considered enabled or disabled. Setting `StatusOverride` to `Enabled` allows the variant, when chosen, to override a flag to be enabled. Setting `StatusOverride` to `Disabled` provides the opposite functionality, therefore disabling the flag when the variant is chosen. A feature with a `Status` of `Disabled` cannot be overridden. +You can use variants to override the enabled state of a feature flag. This gives variants an opportunity to extend the evaluation of a feature flag. If a caller is checking whether a flag that has variants is enabled, the feature manager will check if the variant assigned to the current user is set up to override the result. This is done using the optional variant property `status_override`. By default, this property is set to `None`, which means the variant doesn't affect whether the flag is considered enabled or disabled. Setting `status_override` to `Enabled` allows the variant, when chosen, to override a flag to be enabled. Setting `status_override` to `Disabled` provides the opposite functionality, therefore disabling the flag when the variant is chosen. A feature with a `Status` of `Disabled` cannot be overridden. -If you are using a feature flag with binary variants, the `StatusOverride` property can be very helpful. It allows you to continue using APIs like `IsEnabledAsync` and `FeatureGateAttribute` in your application, all while benefiting from the new features that come with variants, such as percentile allocation and seed. +If you are using a feature flag with binary variants, the `status_override` property can be very helpful. It allows you to continue using APIs like `IsEnabledAsync` and `FeatureGateAttribute` in your application, all while benefiting from the new features that come with variants, such as percentile allocation and seed. ``` javascript -"Allocation": { - "Percentile": [ +{ + "id": "MyVariantFeatureFlag", + "enabled": true, + "allocation": { + "percentile": [ + { + "variant": "On", + "from": 10, + "to": 20 + } + ], + "default_when_enabled": "Off", + "seed": "Enhanced-Feature-Group" + }, + "variants": [ { - "Variant": "On", - "From": 10, - "To": 20 + "name": "On" + }, + { + "name": "Off", + "status_override": "Disabled" } - ], - "DefaultWhenEnabled": "Off", - "Seed": "Enhanced-Feature-Group" -}, -"Variants": [ - { - "Name": "On" - }, - { - "Name": "Off", - "StatusOverride": "Disabled" - } -], -"EnabledFor": [ - { - "Name": "AlwaysOn" - } -] + ] +} ``` -In the above example, the feature is enabled by the `AlwaysOn` filter. If the current user is in the calculated percentile range of 10 to 20, then the `On` variant is returned. Otherwise, the `Off` variant is returned and because `StatusOverride` is equal to `Disabled`, the feature will now be considered disabled. +In the above example, the feature is always enabled. If the current user is in the calculated percentile range of 10 to 20, then the `On` variant is returned. Otherwise, the `Off` variant is returned and because `status_override` is equal to `Disabled`, the feature will now be considered disabled. ### Variants in Dependency Injection @@ -1030,14 +937,14 @@ The call above makes `IVariantServiceProvider` available in the serv ``` javascript { // The example variant feature flag - "ForecastAlgorithm": { - "Variants": [ - { - "Name": "AlgorithmBeta" - }, - ... - ] - } + "id": "ForecastAlgorithm", + "enabled": true, + "variants": [ + { + "Name": "AlgorithmBeta" + }, + ... + ] } ``` @@ -1068,35 +975,32 @@ These types of questions can be answered through the emission and analysis of fe By default, feature flags will not have telemetry emitted. To publish telemetry for a given feature flag, the flag *MUST* declare that it is enabled for telemetry emission. -For flags defined in `appsettings.json`, that is done by using the `Telemetry` property on feature flags. +For flags defined in `appsettings.json`, that is done by using the `telemetry` property on feature flags. ``` javascript { - "FeatureManagement": - { - "MyFlag": - { - "Telemetry": { - "Enabled": true - }, - "EnabledFor": [ - { - "Name": "AlwaysOn" + "feature_management": { + "feature_flags": [ + { + "id": "MyFeatureFlag", + "enabled": true, + "telemetry": { + "enabled": true } - ] - } + } + ] } } ``` -The appsettings snippet above defines a feature flag named `MyFlag` that is enabled for telemetry. This is indicated by the `Telemetry` object which sets `Enabled` to true. The value of the `Enabled` property must be `true` to publish telemetry for the flag. +The appsettings snippet above defines a feature flag named `MyFeatureFlag` that is enabled for telemetry. This is indicated by the `telemetry` object which sets `enabled` to true. The value of the `enabled` property must be `true` to publish telemetry for the flag. -The `Telemetry` section of a feature flag has the following properties: +The `telemetry` section of a feature flag has the following properties: | Property | Description | | ---------------- | ---------------- | -| `Enabled` | Specifies whether telemetry should be published for the feature flag. | -| `Metadata` | A collection of key-value pairs, modeled as a dictionary, that can be used to attach custom metadata about the feature flag to evaluation events. | +| `enabled` | Specifies whether telemetry should be published for the feature flag. | +| `metadata` | A collection of key-value pairs, modeled as a dictionary, that can be used to attach custom metadata about the feature flag to evaluation events. | ### Custom Telemetry Publishers diff --git a/schemas/FeatureManagement.Dotnet.v2.0.0.schema.json b/schemas/FeatureManagement.Dotnet.v2.0.0.schema.json deleted file mode 100644 index 7d25cf06..00000000 --- a/schemas/FeatureManagement.Dotnet.v2.0.0.schema.json +++ /dev/null @@ -1,313 +0,0 @@ -{ - "definitions": {}, - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "title": "A .NET Feature Management Configuration", - "required": [ - "FeatureManagement" - ], - "properties":{ - "FeatureManagement": { - "type": "object", - "title": "Feature Management", - "description": "Declares feature management configuration.", - "required": [], - "patternProperties": { - "^[^:]*$": { - "description": "Declares a feature flag.", - "anyOf": [ - { - "type": "boolean", - "title": "On/Off Feature Flag", - "description": "A feature flag that always returns the same value." - }, - { - "type": "object", - "title": "Conditional Feature Flag", - "description": "A feature flag which value is dynamic based on a set of feature filters", - "required": [ - "EnabledFor" - ], - "properties": { - "Status": { - "type": "string", - "title": "Feature Status", - "description": "Describes how a feature's state will be evaluated. When set to Conditional, the state of the feature is conditional upon the feature evaluation pipeline. When set to Disabled, the state of feature is always disabled.", - "enum": [ - "Conditional", - "Disabled" - ], - "default": "Conditional" - }, - "RequirementType": { - "type": "string", - "title": "Requirement Type", - "description": "Determines whether any or all registered feature filters must be enabled for the feature to be considered enabled.", - "enum": [ - "Any", - "All" - ], - "default": "Any" - }, - "EnabledFor": { - "oneOf": [ - { - "type": "array", - "title": "Feature Filter Collection", - "description": "Feature filters that are evaluated to conditionally enable the flag.", - "items": { - "type": "object", - "title": "Feature Filter Declaration", - "required": [ - "Name" - ], - "properties": { - "Name": { - "type": "string", - "title": "Feature Filter Name", - "description": "The name used to refer to and require a feature filter.", - "default": "", - "examples": [ - "Percentage", - "TimeWindow" - ], - "pattern": "^[^:]*$" - }, - "Parameters": { - "type": "object", - "title": "Feature Filter Parameters", - "description": "Custom parameters for a given feature filter. A feature filter can require any set of parameters of any type.", - "required": [], - "patternProperties": { - "^.*$": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - }, - { - "type": "object" - }, - { - "type": "number" - }, - { - "type": "array" - }, - { - "type": "boolean" - } - ] - } - } - } - } - } - }, - { - "type": "boolean" - } - ] - }, - "Variants": { - "type": "array", - "title": "Variant Collection", - "description": "The list of variants defined for this feature. A variant represents a configuration value of a feature flag that can be a string, a number, a boolean, or a JSON object.", - "items": { - "type": "object", - "title": "Variant", - "required": [ - "Name" - ], - "properties":{ - "Name": { - "type": "string", - "title": "Variant Name", - "description": "The name used to refer to a feature variant.", - "pattern": "^(.*)$" - }, - "ConfigurationValue": { - "type": ["string", "null", "number", "object", "array", "boolean"], - "title": "Variant Configuration Value", - "description": "The configuration value for this feature variant.", - "default": null - }, - "ConfigurationReference": { - "type": "string", - "title": "Variant Configuration Reference", - "description": "The path to a configuration section used as the configuration value for this feature variant.", - "pattern": "^[a-zA-Z0-9]+(:[a-zA-Z0-9]+)*$" - }, - "StatusOverride": { - "type": "string", - "title": "Variant Status Override", - "description": "Overrides the enabled state of the feature if the given variant is assigned. Does not override the state if value is None.", - "enum": [ - "None", - "Enabled", - "Disabled" - ], - "default": "None" - } - } - } - }, - "Allocation": { - "type": "object", - "title": "Variant Allocation", - "description": "Determines how variants should be allocated for the feature to various users.", - "required": [], - "properties": { - "DefaultWhenDisabled": { - "type": "string", - "title": "Default Variant Allocation When Disabled", - "description": "Specifies which variant should be used when the feature is considered disabled.", - "default": "", - "pattern": "^(.*)$" - }, - "DefaultWhenEnabled": { - "type": "string", - "title": "Default Variant Allocation When Enabled", - "description": "Specifies which variant should be used when the feature is considered enabled and no other allocation rules are applicable.", - "default": "", - "pattern": "^(.*)$" - }, - "User": { - "type": "array", - "title": "User Allocation Collection", - "description": "A list of objects, each containing a variant name and list of users for whom that variant should be used.", - "items": { - "type": "object", - "title": "User Allocation", - "required": [ - "Variant", - "Users" - ], - "properties": { - "Variant": { - "type": "string", - "title": "User Allocation Variant", - "description": "The name of the variant to use if the user allocation matches the current user.", - "pattern": "^(.*)$" - }, - "Users": { - "type": "array", - "title": "User Allocation Users Collection", - "description": "Collection of users where if any match the current user, the variant specified in the user allocation is used.", - "items": { - "type": "string" - } - } - } - } - }, - "Group": { - "type": "array", - "title": "Group Allocation Collection", - "description": "A list of objects, each containing a variant name and list of groups for which that variant should be used.", - "items": { - "type": "object", - "title": "Group Allocation", - "required": [ - "Variant", - "Groups" - ], - "properties": { - "Variant": { - "type": "string", - "title": "Group Allocation Variant", - "description": "The name of the variant to use if the group allocation matches a group the current user is in.", - "pattern": "^(.*)$" - }, - "Groups": { - "type": "array", - "title": "Group Allocation Groups Collection", - "description": "Collection of groups where if the current user is in any of these groups, the variant specified in the group allocation is used.", - "items": { - "type": "string" - } - } - } - } - }, - "Percentile": { - "type": "array", - "title": "Percentile Allocation Collection", - "description": "A list of objects, each containing a variant name and percentage range for which that variant should be used.", - "items": { - "type": "object", - "title": "Percentile Allocation", - "required": [ - "Variant", - "From", - "To" - ], - "properties": { - "Variant": { - "type": "string", - "title": "Percentile Allocation Variant", - "description": "The name of the variant to use if the calculated percentile for the current user falls in the provided range.", - "pattern": "^(.*)$" - }, - "From": { - "type": "number", - "title": "Percentile Allocation From", - "description": "The lower end of the percentage range for which this variant will be used.", - "minimum": 0, - "maximum": 100 - }, - "To": { - "type": "number", - "title": "Percentile Allocation To", - "description": "The upper end of the percentage range for which this variant will be used.", - "minimum": 0, - "maximum": 100 - } - } - } - }, - "Seed": { - "type": "string", - "title": "Percentile Allocation Seed", - "description": "The value percentile calculations are based on. The calculated percentile is consistent across features for a given user if the same nonempty seed is used.", - "default": "", - "pattern": "^(.*)$" - } - } - }, - "Telemetry": { - "type": "object", - "title": "Telemetry Options", - "description": "The declaration of options used to configure telemetry for this feature.", - "required": [], - "properties": { - "Enabled": { - "type": "boolean", - "title": "Telemetry Enabled State", - "description": "Indicates if telemetry is enabled.", - "default": false - }, - "Metadata": { - "type": "object", - "title": "Telemetry Metadata", - "description": "A container for metadata that should be bundled with flag telemetry.", - "required": [], - "patternProperties": { - "^.*$": { - "type": "string" - } - }, - "additionalProperties": false - } - } - } - } - } - ] - } - } - } - } -}