Exemple #1
0
        /// <summary>
        /// Enables Azure App Configuration feature flags to be parsed and transformed into feature management configuration.
        /// </summary>
        /// <param name="configure">A callback used to configure feature flag options.</param>
        public AzureAppConfigurationOptions UseFeatureFlags(Action <FeatureFlagOptions> configure = null)
        {
            FeatureFlagOptions options = new FeatureFlagOptions();

            configure?.Invoke(options);

            if (options.CacheExpirationTime < MinimumFeatureFlagsCacheExpiration)
            {
                throw new ArgumentOutOfRangeException(nameof(options.CacheExpirationTime), options.CacheExpirationTime.TotalMilliseconds,
                                                      string.Format(Constants.ErrorMessages.CacheExpirationTimeTooShort, MinimumFeatureFlagsCacheExpiration.TotalMilliseconds));
            }

            if (!(_kvSelectors.Any(selector => selector.KeyFilter.StartsWith(FeatureManagementConstants.FeatureFlagMarker) && selector.LabelFilter.Equals(options.Label))))
            {
                Select(FeatureManagementConstants.FeatureFlagMarker + "*", options.Label);
            }

            if (!_adapters.Any(a => a is FeatureManagementKeyValueAdapter))
            {
                _adapters.Add(new FeatureManagementKeyValueAdapter());
            }

            if (!_multiKeyWatchers.Any(kw => kw.Key.Equals(FeatureManagementConstants.FeatureFlagMarker)))
            {
                _multiKeyWatchers.Add(new KeyValueWatcher
                {
                    Key   = FeatureManagementConstants.FeatureFlagMarker,
                    Label = options.Label,
                    CacheExpirationTime = options.CacheExpirationTime
                });
            }

            return(this);
        }
Exemple #2
0
            public FactsBase()
            {
                _storage   = new Mock <IFeatureFlagStorageService>();
                _telemetry = new Mock <IFeatureFlagTelemetryService>();
                _options   = new FeatureFlagOptions();

                _target = new FeatureFlagCacheService(
                    _storage.Object,
                    _options,
                    _telemetry.Object,
                    Mock.Of <ILogger <FeatureFlagCacheService> >());

                _latestFlags = FeatureFlagStateBuilder
                               .Create()
                               .WithFeature("Foo", FeatureStatus.Enabled)
                               .Build();

                _stalenessMetrics = new List <TimeSpan>();
                _telemetry
                .Setup(t => t.TrackFeatureFlagStaleness(It.IsAny <TimeSpan>()))
                .Callback((TimeSpan staleness) =>
                {
                    _stalenessMetrics.Add(staleness);
                });
            }
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;

            options = new FeatureFlagOptions()
                      .UseInMemoryFeatureProvider();
            // .UseCachedSqlFeatureProvider(Configuration.GetConnectionString("localDb"));
        }
 public Startup(IConfiguration configuration)
 {
     Configuration = configuration;
     _options      = new FeatureFlagOptions().UseInMemoryFeatureProvider();
 }
        public static IConfigurationBuilder AddAzureAppConfiguration(
            this IConfigurationBuilder configurationBuilder,
            string currentEnvironment,
            Action <AzureAppConfigConnectOptions, FiltersOptions, FeatureFlagOptions>?configureConnect = default,
            string sectionName = Sections.AzureAppConfig,
            bool throwExceptionOnStoreNotFound = false,
            string?envSectionName = null)
        {
            var configuration = configurationBuilder.Build();

            return(configurationBuilder.AddAzureAppConfiguration(
                       options =>
            {
                var env = new Environments();
                if (!string.IsNullOrEmpty(envSectionName))
                {
                    env.Clear();
                    configuration.Bind(envSectionName, env);
                }

                // create connection options
                var connectOptions = new AzureAppConfigConnectOptions();
                configuration.Bind(sectionName, connectOptions);

                var filtersOptions = new FiltersOptions();
                configuration.Bind($"{sectionName}:Filters", filtersOptions);

                var featuresOptions = new FeatureFlagOptions();
                configuration.Bind($"{sectionName}:Features", featuresOptions);

                configureConnect?.Invoke(connectOptions, filtersOptions, featuresOptions);

                // configure features
                options.UseFeatureFlags(fo =>
                {
                    fo.CacheExpirationInterval = featuresOptions.CacheExpirationInterval;
                    if (!string.IsNullOrEmpty(featuresOptions.Label))
                    {
                        fo.Label = env[featuresOptions.Label];
                    }
                });

                if (!string.IsNullOrEmpty(connectOptions.ConnectionString))
                {
                    options.Connect(connectOptions.ConnectionString);
                }
                else if (connectOptions.Endpoint != null &&
                         string.IsNullOrEmpty(connectOptions.ConnectionString))
                {
                    var credentials = new DefaultAzureCredential();
                    options.Connect(connectOptions.Endpoint, credentials);
                }

                options.ConfigureClientOptions(clientOptions => clientOptions.Retry.MaxRetries = connectOptions.MaxRetries);

                foreach (var section in filtersOptions.Sections)
                {
                    // Load configuration values with no label, which means all of the configurations that are not specific to
                    // Environment
                    options.Select(section);

                    // Override with any configuration values specific to current hosting env
                    options.Select(section, env[currentEnvironment]);
                }

                foreach (var section in filtersOptions.RefresSections)
                {
                    options.ConfigureRefresh(refresh =>
                    {
                        refresh.Register(section, refreshAll: true);
                        refresh.Register(section, env[currentEnvironment], refreshAll: true);
                        refresh.SetCacheExpiration(filtersOptions.CacheExpirationTime);
                    });
                }
            },
                       throwExceptionOnStoreNotFound));
        }