///<inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { string claimType = data.ClaimType?.ToString(); if (claimType != null && percentage > 0) { var user = _httpContextAccessor .HttpContext .User; if (user != null && user.Identity.IsAuthenticated) { var value = user.FindFirst(claimType)?.Value; if (value != null) { // this only apply when claim exist, we apply also some entropy to current claim value. // adding this entropy ensure that not all features with gradual rollout for claim value are enabled/disable at the same time for the same user. var assignedPartition = _partitioner.ResolvePartition(featureName + value, partitions: 100); return(assignedPartition <= percentage); } } } } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string headerName = data.HeaderName; if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { if (percentage > 0d) { var values = _httpContextAccessor.HttpContext .Request .Headers[headerName]; var headerValue = values != StringValues.Empty ? values.First() : NO_HEADER_DEFAULT_VALUE; var assignedPartition = Partitioner.ResolveToLogicalPartition(headerValue, Partitions); return(assignedPartition <= percentage); } } return(false); }
/// <inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string headerName = data.HeaderName; if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { if (percentage > 0d) { var values = _httpContextAccessor.HttpContext .Request .Headers[headerName]; if (values != StringValues.Empty) { // this only apply when header exist, we apply also some entropy to header value. // adding this entropy ensure that not all features with gradual rollout for claim value are enabled/disable at the same time for the same user. var assignedPartition = _partitioner.ResolvePartition(featureName + values.First(), partitions: 100); return(assignedPartition <= percentage); } } } return(false); }
///<inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { if (percentage > 0d) { var sessionId = _httpContextAccessor .HttpContext .Session .Id; // we apply also some entropy to sessionid value. // adding this entropy ensure that not all features with gradual rollout for claim value are enabled/disable at the same time for the same user. var assignedPartition = _partitioner.ResolvePartition(featureName + sessionId); return(assignedPartition <= percentage); } } return(false); }
///<inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var currentUserName = await _userNameProviderService .GetCurrentUserNameAsync(); if (currentUserName != null) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string activeUserNames = data.Users?.ToString(); if (activeUserNames != null) { var tokenizer = new StringTokenizer(activeUserNames, EsquioConstants.DEFAULT_SPLIT_SEPARATOR); return(tokenizer.Contains( currentUserName, StringSegmentComparer.OrdinalIgnoreCase)); } } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { string claimType = data.ClaimType?.ToString(); if (claimType != null && percentage > 0) { var user = _httpContextAccessor .HttpContext .User; if (user != null && user.Identity.IsAuthenticated) { var value = user.FindFirst(claimType)?.Value ?? NO_CLAIMTYPE_DEFAULT_VALUE; var assignedPartition = Partitioner.ResolveToLogicalPartition(value, Partitions); return(assignedPartition <= percentage); } } } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(typeof(ServerIpAddressToggle).FullName); var data = toggle.GetData(); var ipAddress = _contextAccessor.HttpContext.Connection.LocalIpAddress; var bytes = ipAddress.GetAddressBytes(); string ipAddresses = data.IpAddresses; _logger.LogDebug($"{nameof(ServerIpAddressToggle)} is trying to verify if '{ipAddress}' is in the IP list."); var tokenizer = new StringTokenizer(ipAddresses, EsquioConstants.DEFAULT_SPLIT_SEPARATOR); foreach (var token in tokenizer) { if (token.HasValue && IPAddress.TryParse(token, out IPAddress address) && address.GetAddressBytes().SequenceEqual(bytes)) { _logger.LogInformation($"The server IP address '{ipAddress}' is in the IP '{ipAddresses}' list."); return(true); } } _logger.LogInformation($"The server IP address '{ipAddress}' is not in the IP list."); return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { if (percentage > 0d) { try { var sessionId = _httpContextAccessor .HttpContext .Session .Id; var assignedPartition = Partitioner.ResolveToLogicalPartition(sessionId, Partitions); return(assignedPartition <= percentage); } catch (InvalidOperationException) { _logger.LogError($"The toggle {nameof(GradualRolloutSessionToggle)} can't perform rollout on Session because Session has not been configured for this application or request."); } } } return(false); }
///<inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore .FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string claimType = data.ClaimType?.ToString(); string allowedValues = data.ClaimValues?.ToString(); if (claimType != null && allowedValues != null) { var user = _httpContextAccessor.HttpContext.User; if (user != null && user.Identity.IsAuthenticated) { var value = user.FindFirst(claimType)? .Value; if (value != null) { var tokenizer = new StringTokenizer(allowedValues, EsquioConstants.DEFAULT_SPLIT_SEPARATOR); return(tokenizer.Contains( value, StringSegmentComparer.OrdinalIgnoreCase)); } } } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string allowedCountries = data.Countries; string accessKey = data.AccessKey; var currentCountry = await _locationProviderService .GetCountryCode(GetRemoteIpAddress(), accessKey); if (allowedCountries != null && currentCountry != null && accessKey != null) { var tokenizer = new StringTokenizer(allowedCountries, EsquioConstants.DEFAULT_SPLIT_SEPARATOR); return(tokenizer.Contains(currentCountry, StringSegmentComparer.OrdinalIgnoreCase)); } return(false); }
///<inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string headerName = data.HeaderName?.ToString(); string allowedValues = data.HeaderValues?.ToString(); if (headerName != null && allowedValues != null) { var values = _httpContextAccessor.HttpContext .Request .Headers[headerName]; foreach (var item in values) { var tokenizer = new StringTokenizer(allowedValues, SPLIT_SEPARATOR); if (tokenizer.Contains(item, StringSegmentComparer.OrdinalIgnoreCase)) { return(true); } } } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(typeof(HostNameToggle).FullName); var data = toggle.GetData(); string hostNames = data.HostNames; var hostName = _contextAccessor.HttpContext.Request.Host.Host; _logger.LogDebug($"{nameof(HostNameToggle)} is trying to verify if '{hostName}' is in the hostNames list."); var tokenizer = new StringTokenizer(hostNames, EsquioConstants.DEFAULT_SPLIT_SEPARATOR); foreach (var token in tokenizer) { if (token.HasValue && token.Value.Equals(hostName, StringComparison.InvariantCultureIgnoreCase)) { _logger.LogInformation($"The hostname '{hostName}' is in the hostnames '{hostNames}' list."); return(true); } } _logger.LogInformation($"The hostname '{hostName}' is not in the hostnames list."); return(false); }
/// <inheritdoc/> public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore .FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { if (percentage > 0) { var currentUserName = await _userNameProviderService .GetCurrentUserNameAsync(); if (currentUserName != null) { // this only apply for authenticted users, we apply some entropy to currentUserName. // adding this entropy ensure that not all features with gradual rollout for username are enabled/disable at the same time for the same user. var assignedPartition = _partitioner.ResolvePartition(featureName + currentUserName, partitions: 100); return(assignedPartition <= percentage); } } } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(typeof(UserAgentBrowserToggle).FullName); var data = toggle.GetData(); var allowedBrowsers = data.Browsers.ToString(); var currentBrowser = GetCurrentBrowser(); if (allowedBrowsers != null && !String.IsNullOrEmpty(currentBrowser)) { _logger.LogDebug($"{nameof(UserAgentBrowserToggle)} is trying to verify if {currentBrowser} is satisfying allowed browser configuration."); var tokenizer = new StringTokenizer(allowedBrowsers, split_characters); foreach (var segment in tokenizer) { if (segment.Value?.IndexOf(currentBrowser, StringComparison.InvariantCultureIgnoreCase) >= 0) { _logger.LogInformation($"The browser {currentBrowser} is satisfied using {allowedBrowsers} configuration."); return(true); } } } _logger.LogInformation($"The browser {currentBrowser} is not allowed using current toggle configuration."); return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); var fromDate = DateTime.ParseExact(data.From.ToString(), FORMAT_DATE, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); var toDate = DateTime.ParseExact(data.To.ToString(), FORMAT_DATE, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); var now = DateTime.UtcNow; if (now > fromDate && now < toDate) { return(true); } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); string allowedCountries = data.Countries; var currentCountry = await _locationProviderService .GetCountryName(GetRemoteIpAddress()); if (allowedCountries != null && currentCountry != null) { var tokenizer = new StringTokenizer(allowedCountries, split_characters); return(tokenizer.Contains(currentCountry, StringSegmentComparer.OrdinalIgnoreCase)); } return(false); }
public async Task <bool> IsActiveAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { var feature = await _featureStore.FindFeatureAsync(featureName, productName, cancellationToken); var toggle = feature.GetToggle(this.GetType().FullName); var data = toggle.GetData(); if (Double.TryParse(data.Percentage.ToString(), out double percentage)) { if (percentage > 0) { var currentUserName = await _userNameProviderService .GetCurrentUserNameAsync() ?? AnonymousUser; var assignedPartition = Partitioner.ResolveToLogicalPartition(currentUserName, Partitions); return(assignedPartition <= percentage); } } return(false); }
public async Task <bool> IsEnabledAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { try { var totalTime = ValueStopwatch.StartNew(); _diagnostics.BeginFeatureEvaluation(featureName, productName); var feature = await _featureStore .FindFeatureAsync(featureName, productName, cancellationToken); if (feature == null) { _diagnostics.FeatureEvaluationNotFound(featureName, productName); return(_options.NotFoundBehavior == NotFoundBehavior.SetEnabled); } if (!feature.IsEnabled) { _diagnostics.FeatureEvaluationDisabled(featureName, productName); return(false); } var enabled = true; var toggles = feature.GetToggles(); foreach (var toggle in toggles) { _diagnostics.BeginTogglevaluation(featureName, productName, toggle.Type); var active = false; var evaluationTime = ValueStopwatch.StartNew(); var toggleInstance = _toggleActivator .CreateInstance(toggle.Type); if (toggleInstance != null) { active = await toggleInstance?.IsActiveAsync(featureName, productName, cancellationToken); } _diagnostics.Togglevaluation(featureName, productName, toggle.Type, (long)evaluationTime.GetElapsedTime().TotalMilliseconds); _diagnostics.EndTogglevaluation(featureName, productName, toggle.Type, active); if (!active) { _diagnostics.ToggleNotActive(featureName, toggle.Type); enabled = false; break; } } _diagnostics.EndFeatureEvaluation(featureName, productName, (long)totalTime.GetElapsedTime().TotalMilliseconds, enabled); return(enabled); } catch (Exception exception) { _diagnostics.FeatureEvaluationThrow(featureName, productName, exception); if (_options.OnErrorBehavior == OnErrorBehavior.Throw) { throw; } return(_options.OnErrorBehavior == OnErrorBehavior.SetEnabled); } }
public async Task <bool> IsEnabledAsync(string featureName, string productName = null, CancellationToken cancellationToken = default) { try { var totalTime = ValueStopwatch.StartNew(); Log.FeatureServiceProcessingBegin(_logger, featureName, productName); var feature = await _featureStore .FindFeatureAsync(featureName, productName, cancellationToken); if (feature == null) { Log.FeatureServiceNotFoundFeature(_logger, featureName, productName); return(_options.NotFoundBehavior == NotFoundBehavior.SetEnabled); } if (!feature.IsEnabled) { Log.FeatureServiceDisabledFeature(_logger, featureName, productName); return(false); } var enabled = true; var toggles = feature.GetToggles(); foreach (var toggle in toggles) { var active = false; var evaluationTime = ValueStopwatch.StartNew(); var toggleInstance = _toggleActivator .CreateInstance(toggle.Type); if (toggleInstance != null) { active = await toggleInstance?.IsActiveAsync(featureName, productName, cancellationToken); } Counters.Instance .ToggleEvaluationTime( featureName: featureName, toggleName: toggle.Type, elapsedMilliseconds: evaluationTime.GetElapsedTime().TotalMilliseconds); if (!active) { Log.FeatureServiceToggleIsNotActive(_logger, featureName, productName); enabled = false; break; } } Counters.Instance .FeatureEvaluationTime( featureName: featureName, elapsedMilliseconds: totalTime.GetElapsedTime().TotalMilliseconds); return(enabled); } catch (Exception exception) { Log.FeatureServiceProcessingFail(_logger, featureName, productName, exception); if (_options.OnErrorBehavior == OnErrorBehavior.Throw) { throw; } return(_options.OnErrorBehavior == OnErrorBehavior.SetEnabled); } }