public AzureAppConfigurationProvider(ConfigurationClient client, AzureAppConfigurationOptions options, bool optional)
        {
            _client   = client ?? throw new ArgumentNullException(nameof(client));
            _options  = options ?? throw new ArgumentNullException(nameof(options));
            _optional = optional;

            IEnumerable <KeyValueWatcher> watchers = options.ChangeWatchers.Union(options.MultiKeyWatchers);

            if (watchers.Any())
            {
                MinCacheExpirationTime = watchers.Min(w => w.CacheExpirationTime);
            }
            else
            {
                MinCacheExpirationTime = AzureAppConfigurationRefreshOptions.DefaultCacheExpirationTime;
            }

            // Enable request tracing if not opt-out
            string requestTracingDisabled = null;

            try
            {
                requestTracingDisabled = Environment.GetEnvironmentVariable(RequestTracingConstants.RequestTracingDisabledEnvironmentVariable);
            }
            catch (SecurityException) { }
            _requestTracingEnabled = bool.TryParse(requestTracingDisabled, out bool tracingDisabled) ? !tracingDisabled : true;

            if (_requestTracingEnabled)
            {
                _hostType = TracingUtils.GetHostType();
            }
        }
 private void SetRequestTracingOptions()
 {
     _requestTracingOptions = new RequestTracingOptions
     {
         HostType                    = TracingUtils.GetHostType(),
         IsDevEnvironment            = TracingUtils.IsDevEnvironment(),
         IsKeyVaultConfigured        = _options.IsKeyVaultConfigured,
         IsKeyVaultRefreshConfigured = _options.IsKeyVaultRefreshConfigured
     };
 }
        private async ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            string headerValue = message.Request.Headers.TryGetValue(RequestTracingConstants.UserAgentHeader, out string sdkUserAgent)
                ? TracingUtils.GenerateUserAgent(sdkUserAgent) : TracingUtils.GenerateUserAgent();

            message.Request.Headers.SetValue(RequestTracingConstants.UserAgentHeader, headerValue);

            if (async)
            {
                await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
            }
            else
            {
                ProcessNext(message, pipeline);
            }
        }
        public AzureAppConfigurationProvider(ConfigurationClient client, AzureAppConfigurationOptions options, bool optional)
        {
            _client   = client ?? throw new ArgumentNullException(nameof(client));
            _options  = options ?? throw new ArgumentNullException(nameof(options));
            _optional = optional;

            // Enable request tracing if not opt-out
            string requestTracingDisabled = null;

            try
            {
                requestTracingDisabled = Environment.GetEnvironmentVariable(RequestTracingConstants.RequestTracingDisabledEnvironmentVariable);
            }
            catch (SecurityException) { }
            _requestTracingEnabled = bool.TryParse(requestTracingDisabled, out bool tracingDisabled) ? !tracingDisabled : true;

            if (_requestTracingEnabled)
            {
                _hostType = TracingUtils.GetHostType();
            }
        }
 private async Task CallWithRequestTracing(Func <Task> clientCall)
 {
     var requestType = _isInitialLoadComplete ? RequestType.Watch : RequestType.Startup;
     await TracingUtils.CallWithRequestTracing(_requestTracingEnabled, requestType, _hostType, clientCall).ConfigureAwait(false);
 }
        private async Task RefreshIndividualKeyValues()
        {
            bool shouldRefreshAll = false;

            foreach (KeyValueWatcher changeWatcher in _options.ChangeWatchers)
            {
                string watchedKey   = changeWatcher.Key;
                string watchedLabel = changeWatcher.Label;
                var    timeElapsedSinceLastRefresh = DateTimeOffset.UtcNow - changeWatcher.LastRefreshTime;

                // Skip the refresh for this key if the cached value has not expired or a refresh operation is in progress
                if (timeElapsedSinceLastRefresh < changeWatcher.CacheExpirationTime || !changeWatcher.Semaphore.Wait(0))
                {
                    continue;
                }

                try
                {
                    bool hasChanged = false;
                    ConfigurationSetting watchedKv = null;

                    if (_settings.ContainsKey(watchedKey) && _settings[watchedKey].Label == watchedLabel.NormalizeNull())
                    {
                        watchedKv = _settings[watchedKey];

                        KeyValueChange keyValueChange = default;
                        await TracingUtils.CallWithRequestTracing(_requestTracingEnabled, RequestType.Watch, _hostType,
                                                                  async() => keyValueChange = await _client.GetKeyValueChange(watchedKv, CancellationToken.None).ConfigureAwait(false)).ConfigureAwait(false);

                        changeWatcher.LastRefreshTime = DateTimeOffset.UtcNow;

                        // Check if a change has been detected in the key-value registered for refresh
                        if (keyValueChange.ChangeType != KeyValueChangeType.None)
                        {
                            ProcessChanges(Enumerable.Repeat(keyValueChange, 1));
                            hasChanged = true;
                        }
                    }
                    else
                    {
                        // Load the key-value in case the previous load attempts had failed
                        var options = new SettingSelector {
                            LabelFilter = watchedLabel
                        };

                        try
                        {
                            await CallWithRequestTracing(async() => watchedKv = await _client.GetConfigurationSettingAsync(watchedKey, watchedLabel, CancellationToken.None).ConfigureAwait(false)).ConfigureAwait(false);
                        }
                        catch (RequestFailedException e) when(e.Status == (int)HttpStatusCode.NotFound)
                        {
                            watchedKv = null;
                        }

                        changeWatcher.LastRefreshTime = DateTimeOffset.UtcNow;

                        if (watchedKv != null)
                        {
                            // Add the key-value if it is not loaded, or update it if it was loaded with a different label
                            _settings[watchedKey] = watchedKv;
                            hasChanged            = true;
                        }
                    }

                    if (hasChanged)
                    {
                        if (changeWatcher.RefreshAll)
                        {
                            shouldRefreshAll = true;

                            // Skip refresh for other key-values since refreshAll will populate configuration from scratch
                            break;
                        }
                        else
                        {
                            await SetData(_settings).ConfigureAwait(false);
                        }
                    }
                }
                finally
                {
                    changeWatcher.Semaphore.Release();
                }
            }

            // Trigger a single refresh-all operation if a change was detected in one or more key-values with refreshAll: true
            if (shouldRefreshAll)
            {
                await LoadAll(ignoreFailures : false).ConfigureAwait(false);
            }
        }
Beispiel #7
0
        private async Task RefreshIndividualKeyValues()
        {
            bool shouldRefreshAll = false;

            foreach (KeyValueWatcher changeWatcher in _options.ChangeWatchers)
            {
                string watchedKey   = changeWatcher.Key;
                string watchedLabel = changeWatcher.Label;

                // Skip the refresh for this key if the cached value has not expired or a refresh operation is in progress
                if (DateTimeOffset.UtcNow < changeWatcher.CacheExpires || !changeWatcher.Semaphore.Wait(0))
                {
                    continue;
                }

                try
                {
                    bool hasChanged = false;
                    KeyValueIdentifier watchedKeyLabel = new KeyValueIdentifier(watchedKey, watchedLabel);

                    if (_watchedSettings.TryGetValue(watchedKeyLabel, out ConfigurationSetting watchedKv))
                    {
                        KeyValueChange keyValueChange = default;
                        await TracingUtils.CallWithRequestTracing(_requestTracingEnabled, RequestType.Watch, _hostType,
                                                                  async() => keyValueChange = await _client.GetKeyValueChange(watchedKv, CancellationToken.None).ConfigureAwait(false)).ConfigureAwait(false);

                        changeWatcher.CacheExpires = DateTimeOffset.UtcNow.Add(changeWatcher.CacheExpirationInterval);

                        // Check if a change has been detected in the key-value registered for refresh
                        if (keyValueChange.ChangeType != KeyValueChangeType.None)
                        {
                            if (changeWatcher.RefreshAll)
                            {
                                shouldRefreshAll = true;
                                break;
                            }

                            if (keyValueChange.ChangeType == KeyValueChangeType.Deleted)
                            {
                                _watchedSettings.TryRemove(watchedKeyLabel, out ConfigurationSetting _);
                            }
                            else if (keyValueChange.ChangeType == KeyValueChangeType.Modified)
                            {
                                _watchedSettings[watchedKeyLabel] = keyValueChange.Current;
                            }

                            hasChanged = true;
                            ProcessChanges(Enumerable.Repeat(keyValueChange, 1));
                        }
                    }
                    else
                    {
                        // Load the key-value in case the previous load attempts had failed
                        var options = new SettingSelector {
                            LabelFilter = watchedLabel
                        };

                        try
                        {
                            await CallWithRequestTracing(async() => watchedKv = await _client.GetConfigurationSettingAsync(watchedKey, watchedLabel, CancellationToken.None).ConfigureAwait(false)).ConfigureAwait(false);
                        }
                        catch (RequestFailedException e) when(e.Status == (int)HttpStatusCode.NotFound)
                        {
                            watchedKv = null;
                        }

                        changeWatcher.CacheExpires = DateTimeOffset.UtcNow.Add(changeWatcher.CacheExpirationInterval);

                        if (watchedKv != null)
                        {
                            if (changeWatcher.RefreshAll)
                            {
                                shouldRefreshAll = true;
                                break;
                            }

                            hasChanged = true;

                            // Add the key-value if it is not loaded, or update it if it was loaded with a different label
                            _applicationSettings[watchedKey]  = watchedKv;
                            _watchedSettings[watchedKeyLabel] = watchedKv;
                        }
                    }

                    if (hasChanged)
                    {
                        await SetData(_applicationSettings).ConfigureAwait(false);
                    }
                }
                finally
                {
                    changeWatcher.Semaphore.Release();
                }
            }

            // Trigger a single refresh-all operation if a change was detected in one or more key-values with refreshAll: true
            if (shouldRefreshAll)
            {
                await LoadAll(ignoreFailures : false).ConfigureAwait(false);
            }
        }
        private Task CallWithRequestTracing(Func <Task> clientCall)
        {
            var requestType = _isInitialLoadComplete ? RequestType.Watch : RequestType.Startup;

            return(TracingUtils.CallWithRequestTracing(_requestTracingEnabled, requestType, _requestTracingOptions, clientCall));
        }