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); } }
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)); }