예제 #1
0
        private EvaluateResult EvaluateLogic(ProjectConfig projectConfig, string key, string logDefaultValue, string logDefaultVariationId, User user = null)
        {
            if (!this.configDeserializer.TryDeserialize(projectConfig.JsonString, out var deserialized))
            {
                this.log.Warning("Config deserialization failed, returning defaultValue");

                return(null);
            }

            var settings = deserialized.Settings;

            if (!settings.TryGetValue(key, out var setting))
            {
                var keys = string.Join(",", settings.Keys.Select(s => $"'{s}'").ToArray());

                this.log.Error($"Evaluating '{key}' failed. Returning default value: '{logDefaultValue}'. Here are the available keys: {keys}.");

                return(null);
            }

            var evaluateLog = new EvaluateLogger <string>
            {
                ReturnValue = logDefaultValue,
                User        = user,
                KeyName     = key,
                VariationId = logDefaultVariationId
            };

            try
            {
                EvaluateResult result = null;

                if (user != null)
                {
                    // evaluate rules

                    if (TryEvaluateRules(setting.RolloutRules, user, evaluateLog, out result))
                    {
                        evaluateLog.ReturnValue = result.RawValue;
                        evaluateLog.VariationId = result.VariationId;

                        return(result);
                    }

                    // evaluate variations

                    if (TryEvaluateVariations(setting.RolloutPercentageItems, key, user, out result))
                    {
                        evaluateLog.Log("evaluate % option => user targeted");
                        evaluateLog.ReturnValue = result.RawValue;
                        evaluateLog.VariationId = result.VariationId;

                        return(result);
                    }
                    else
                    {
                        evaluateLog.Log("evaluate % option => user not targeted");
                    }
                }
                else if (user == null && (setting.RolloutRules.Any() || setting.RolloutPercentageItems.Any()))
                {
                    this.log.Warning($"Evaluating '{key}'. UserObject missing! You should pass a UserObject to GetValue() or GetValueAsync(), in order to make targeting work properly. Read more: https://configcat.com/docs/advanced/user-object");
                }

                // regular evaluate

                result = new EvaluateResult(setting.RawValue, setting.VariationId);

                evaluateLog.ReturnValue = result.RawValue;
                evaluateLog.VariationId = result.VariationId;

                return(result);
            }
            finally
            {
                this.log.Information(evaluateLog.ToString());
            }
        }
예제 #2
0
        private static bool TryEvaluateRules <T>(ICollection <RolloutRule> rules, User user, EvaluateLogger <T> logger, out EvaluateResult result)
        {
            result = new EvaluateResult();

            if (rules != null && rules.Count > 0)
            {
                foreach (var rule in rules.OrderBy(o => o.Order))
                {
                    result.RawValue    = rule.RawValue;
                    result.VariationId = rule.VariationId;

                    if (!user.AllAttributes.ContainsKey(rule.ComparisonAttribute))
                    {
                        continue;
                    }

                    var comparisonAttributeValue = user.AllAttributes[rule.ComparisonAttribute];
                    if (string.IsNullOrEmpty(comparisonAttributeValue))
                    {
                        continue;
                    }

                    string l = $"evaluate rule: '{comparisonAttributeValue}' {EvaluateLogger<T>.FormatComparator(rule.Comparator)} '{rule.ComparisonValue}' => ";

                    switch (rule.Comparator)
                    {
                    case ComparatorEnum.In:

                        if (rule.ComparisonValue
                            .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select(t => t.Trim())
                            .Contains(comparisonAttributeValue))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.NotIn:

                        if (!rule.ComparisonValue
                            .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select(t => t.Trim())
                            .Contains(comparisonAttributeValue))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.Contains:

                        if (comparisonAttributeValue.Contains(rule.ComparisonValue))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.NotContains:

                        if (!comparisonAttributeValue.Contains(rule.ComparisonValue))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.SemVerIn:
                    case ComparatorEnum.SemVerNotIn:
                    case ComparatorEnum.SemVerLessThan:
                    case ComparatorEnum.SemVerLessThanEqual:
                    case ComparatorEnum.SemVerGreaterThan:
                    case ComparatorEnum.SemVerGreaterThanEqual:

                        if (EvaluateSemVer(comparisonAttributeValue, rule.ComparisonValue, rule.Comparator))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.NumberEqual:
                    case ComparatorEnum.NumberNotEqual:
                    case ComparatorEnum.NumberLessThan:
                    case ComparatorEnum.NumberLessThanEqual:
                    case ComparatorEnum.NumberGreaterThan:
                    case ComparatorEnum.NumberGreaterThanEqual:

                        if (EvaluateNumber(comparisonAttributeValue, rule.ComparisonValue, rule.Comparator))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.SensitiveOneOf:
                        if (rule.ComparisonValue
                            .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select(t => t.Trim())
                            .Contains(HashUtils.HashString(comparisonAttributeValue)))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    case ComparatorEnum.SensitiveNotOneOf:
                        if (!rule.ComparisonValue
                            .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select(t => t.Trim())
                            .Contains(HashUtils.HashString(comparisonAttributeValue)))
                        {
                            logger.Log(l + "match");

                            return(true);
                        }

                        logger.Log(l + "no match");

                        break;

                    default:
                        break;
                    }
                }
            }

            return(false);
        }