Esempio n. 1
0
        public void GetExistingFeature()
        {
            InitStore();
            var result = store.Get(VersionedDataKind.Features, feature1.Key);

            Assert.Equal(feature1.Key, result.Key);
        }
Esempio n. 2
0
        private JToken Evaluate(string featureKey, User user, JToken defaultValue, JTokenType?expectedType)
        {
            if (!Initialized())
            {
                Logger.LogWarning("LaunchDarkly client has not yet been initialized. Returning default");
                return(defaultValue);
            }
            if (user == null || user.Key == null)
            {
                Logger.LogWarning("Feature flag evaluation called with null user or null user key. Returning default");
                sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, null);
                return(defaultValue);
            }

            try
            {
                var featureFlag = _featureStore.Get(featureKey);
                if (featureFlag == null)
                {
                    Logger.LogWarning("Unknown feature flag " + featureKey + "; returning default value: ");
                    sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, null);
                    return(defaultValue);
                }

                FeatureFlag.EvalResult evalResult = featureFlag.Evaluate(user, _featureStore);
                if (!IsOffline())
                {
                    foreach (var prereqEvent in evalResult.PrerequisiteEvents)
                    {
                        _eventStore.Add(prereqEvent);
                    }
                }
                if (evalResult.Result != null)
                {
                    if (expectedType != null && !evalResult.Result.Type.Equals(expectedType))
                    {
                        Logger.LogError("Expected type: " + expectedType + " but got " + evalResult.GetType() +
                                        " when evaluating FeatureFlag: " + featureKey + ". Returning default");
                        sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, featureFlag.Version);
                        return(defaultValue);
                    }
                    sendFlagRequestEvent(featureKey, user, evalResult.Result, defaultValue, featureFlag.Version);
                    return(evalResult.Result);
                }
            }
            catch (Exception e)
            {
                Logger.LogError(
                    String.Format(
                        "Encountered exception in LaunchDarkly client: {0} when evaluating feature key: {1} for user key: {2}",
                        e.Message, featureKey, user.Key));
                Logger.LogDebug(e.ToString());
            }
            sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, null);
            return(defaultValue);
        }
Esempio n. 3
0
        // Returning either a nil EvalResult or EvalResult.value indicates prereq failure/error.
        private EvalResult Evaluate(User user, IFeatureStore featureStore, IList <FeatureRequestEvent> events,
                                    EventFactory eventFactory)
        {
            var prereqOk = true;

            if (Prerequisites != null)
            {
                foreach (var prereq in Prerequisites)
                {
                    var        prereqFeatureFlag = featureStore.Get(VersionedDataKind.Features, prereq.Key);
                    EvalResult prereqEvalResult  = new EvalResult(null, null, events);
                    if (prereqFeatureFlag == null)
                    {
                        Log.ErrorFormat("Could not retrieve prerequisite flag: {0} when evaluating: {1}",
                                        prereq.Key,
                                        Key);
                        return(new EvalResult(null, null, events));
                    }
                    else if (prereqFeatureFlag.On)
                    {
                        prereqEvalResult = prereqFeatureFlag.Evaluate(user, featureStore, events, eventFactory);
                        try
                        {
                            if (prereqEvalResult.Variation != prereq.Variation)
                            {
                                prereqOk = false;
                            }
                        }
                        catch (EvaluationException e)
                        {
                            Log.WarnFormat("Error evaluating prerequisites: {0}",
                                           e,
                                           Util.ExceptionMessage(e));

                            prereqOk = false;
                        }
                    }
                    else
                    {
                        prereqOk = false;
                    }
                    //We don't short circuit and also send events for each prereq.
                    events.Add(eventFactory.NewPrerequisiteFeatureRequestEvent(prereqFeatureFlag,
                                                                               user, null, prereqEvalResult.Result, this));
                }
            }
            if (prereqOk)
            {
                int?   index  = EvaluateIndex(user, featureStore);
                JToken result = GetVariation(index);
                return(new EvalResult(index, result, events));
            }
            return(new EvalResult(null, null, events));
        }
Esempio n. 4
0
        // Returning either a nil EvalResult or EvalResult.value indicates prereq failure/error.
        private JToken Evaluate(User user, IFeatureStore featureStore, IList <FeatureRequestEvent> events, Configuration config)
        {
            var prereqOk = true;

            if (Prerequisites != null)
            {
                foreach (var prereq in Prerequisites)
                {
                    var    prereqFeatureFlag = featureStore.Get(VersionedDataKind.Features, prereq.Key);
                    JToken prereqEvalResult  = null;
                    if (prereqFeatureFlag == null)
                    {
                        Log.ErrorFormat("Could not retrieve prerequisite flag: {0} when evaluating: {1}",
                                        prereq.Key,
                                        Key);
                        return(null);
                    }
                    else if (prereqFeatureFlag.On)
                    {
                        prereqEvalResult = prereqFeatureFlag.Evaluate(user, featureStore, events, config);
                        try
                        {
                            JToken variation = prereqFeatureFlag.GetVariation(prereq.Variation);
                            if (prereqEvalResult == null || variation == null || !prereqEvalResult.Equals(variation))
                            {
                                prereqOk = false;
                            }
                        }
                        catch (EvaluationException e)
                        {
                            Log.WarnFormat("Error evaluating prerequisites: {0}",
                                           e,
                                           Util.ExceptionMessage(e));

                            prereqOk = false;
                        }
                    }
                    else
                    {
                        prereqOk = false;
                    }
                    //We don't short circuit and also send events for each prereq.
                    events.Add(new FeatureRequestEvent(prereqFeatureFlag.Key, EventUser.FromUser(user, config),
                                                       prereqEvalResult, null, prereqFeatureFlag.Version, prereq.Key));
                }
            }
            if (prereqOk)
            {
                return(GetVariation(EvaluateIndex(user, featureStore)));
            }
            return(null);
        }
Esempio n. 5
0
        // Returning either a nil EvalResult or EvalResult.value indicates prereq failure/error.
        private JToken Evaluate(User user, IFeatureStore featureStore, IList <FeatureRequestEvent> events)
        {
            var prereqOk = true;

            if (Prerequisites != null)
            {
                foreach (var prereq in Prerequisites)
                {
                    var    prereqFeatureFlag = featureStore.Get(prereq.Key);
                    JToken prereqEvalResult  = null;
                    if (prereqFeatureFlag == null)
                    {
                        Logger.LogError("Could not retrieve prerequisite flag: " + prereq.Key + " when evaluating: " +
                                        Key);
                        return(null);
                    }
                    else if (prereqFeatureFlag.On)
                    {
                        prereqEvalResult = prereqFeatureFlag.Evaluate(user, featureStore, events);
                        try
                        {
                            JToken variation = prereqFeatureFlag.GetVariation(prereq.Variation);
                            if (prereqEvalResult == null || variation == null || !prereqEvalResult.Equals(variation))
                            {
                                prereqOk = false;
                            }
                        }
                        catch (EvaluationException e)
                        {
                            Logger.LogWarning("Error evaluating prerequisites: " + e.Message, e);
                            prereqOk = false;
                        }
                    }
                    else
                    {
                        prereqOk = false;
                    }
                    //We don't short circuit and also send events for each prereq.
                    events.Add(new FeatureRequestEvent(prereqFeatureFlag.Key, user, prereqEvalResult, null,
                                                       prereqFeatureFlag.Version, prereq.Key));
                }
            }
            if (prereqOk)
            {
                return(GetVariation(EvaluateIndex(user)));
            }
            return(null);
        }
Esempio n. 6
0
 internal bool MatchesUser(User user, IFeatureStore store)
 {
     if (Op == "segmentMatch")
     {
         foreach (var value in Values)
         {
             Segment segment = store.Get(VersionedDataKind.Segments, value.Value <string>());
             if (segment != null && segment.MatchesUser(user))
             {
                 return(MaybeNegate(true));
             }
         }
         return(MaybeNegate(false));
     }
     else
     {
         return(MatchesUserNoSegments(user));
     }
 }
Esempio n. 7
0
 // Checks prerequisites if any; returns null if successful, or an EvaluationReason if we have to
 // short-circuit due to a prerequisite failure.
 private EvaluationReason CheckPrerequisites(User user, IFeatureStore featureStore, IList <FeatureRequestEvent> events,
                                             EventFactory eventFactory)
 {
     if (Prerequisites == null || Prerequisites.Count == 0)
     {
         return(null);
     }
     foreach (var prereq in Prerequisites)
     {
         var prereqOk          = true;
         var prereqFeatureFlag = featureStore.Get(VersionedDataKind.Features, prereq.Key);
         if (prereqFeatureFlag == null)
         {
             Log.ErrorFormat("Could not retrieve prerequisite flag \"{0}\" when evaluating \"{1}\"",
                             prereq.Key, Key);
             prereqOk = false;
         }
         else
         {
             var prereqEvalResult = prereqFeatureFlag.Evaluate(user, featureStore, events, eventFactory);
             // Note that if the prerequisite flag is off, we don't consider it a match no matter
             // what its off variation was. But we still need to evaluate it in order to generate
             // an event.
             if (!prereqFeatureFlag.On || prereqEvalResult.VariationIndex == null || prereqEvalResult.VariationIndex.Value != prereq.Variation)
             {
                 prereqOk = false;
             }
             events.Add(eventFactory.NewPrerequisiteFeatureRequestEvent(prereqFeatureFlag, user,
                                                                        prereqEvalResult, this));
         }
         if (!prereqOk)
         {
             return(new EvaluationReason.PrerequisiteFailed(prereq.Key));
         }
     }
     return(null);
 }
Esempio n. 8
0
        private JToken Evaluate(string featureKey, User user, JToken defaultValue, JTokenType?expectedType)
        {
            if (!Initialized())
            {
                Log.Warn("LaunchDarkly client has not yet been initialized. Returning default");
                return(defaultValue);
            }
            if (user == null || user.Key == null)
            {
                Log.Warn("Feature flag evaluation called with null user or null user key. Returning default");
                sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, null);
                return(defaultValue);
            }

            try
            {
                var featureFlag = _featureStore.Get(VersionedDataKind.Features, featureKey);
                if (featureFlag == null)
                {
                    Log.InfoFormat("Unknown feature flag {0}; returning default value",
                                   featureKey);

                    sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, null);
                    return(defaultValue);
                }

                FeatureFlag.EvalResult evalResult = featureFlag.Evaluate(user, _featureStore, _configuration);
                if (!IsOffline())
                {
                    foreach (var prereqEvent in evalResult.PrerequisiteEvents)
                    {
                        _eventStore.Add(prereqEvent);
                    }
                }
                if (evalResult.Result != null)
                {
                    if (expectedType != null && !evalResult.Result.Type.Equals(expectedType))
                    {
                        Log.ErrorFormat("Expected type: {0} but got {1} when evaluating FeatureFlag: {2}. Returning default",
                                        expectedType,
                                        evalResult.GetType(),
                                        featureKey);

                        sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, featureFlag.Version);
                        return(defaultValue);
                    }
                    sendFlagRequestEvent(featureKey, user, evalResult.Result, defaultValue, featureFlag.Version);
                    return(evalResult.Result);
                }
            }
            catch (Exception e)
            {
                Log.ErrorFormat("Encountered exception in LaunchDarkly client: {0} when evaluating feature key: {1} for user key: {2}",
                                e,
                                Util.ExceptionMessage(e),
                                featureKey,
                                user.Key);

                Log.Debug("{0}", e);
            }
            sendFlagRequestEvent(featureKey, user, defaultValue, defaultValue, null);
            return(defaultValue);
        }
Esempio n. 9
0
        private EvaluationDetail <JToken> Evaluate(string featureKey, User user, JToken defaultValue, JTokenType?expectedType,
                                                   EventFactory eventFactory)
        {
            if (!Initialized())
            {
                if (_featureStore.Initialized())
                {
                    Log.Warn("Flag evaluation before client initialized; using last known values from feature store");
                }
                else
                {
                    Log.Warn("Flag evaluation before client initialized; feature store unavailable, returning default value");
                    return(new EvaluationDetail <JToken>(defaultValue, null,
                                                         new EvaluationReason.Error(EvaluationErrorKind.CLIENT_NOT_READY)));
                }
            }

            FeatureFlag featureFlag = null;

            try
            {
                featureFlag = _featureStore.Get(VersionedDataKind.Features, featureKey);
                if (featureFlag == null)
                {
                    Log.InfoFormat("Unknown feature flag {0}; returning default value",
                                   featureKey);

                    _eventProcessor.SendEvent(eventFactory.NewUnknownFeatureRequestEvent(featureKey, user, defaultValue,
                                                                                         EvaluationErrorKind.FLAG_NOT_FOUND));
                    return(new EvaluationDetail <JToken>(defaultValue, null,
                                                         new EvaluationReason.Error(EvaluationErrorKind.FLAG_NOT_FOUND)));
                }

                if (user == null || user.Key == null)
                {
                    Log.Warn("Feature flag evaluation called with null user or null user key. Returning default");
                    _eventProcessor.SendEvent(eventFactory.NewDefaultFeatureRequestEvent(featureFlag, user, defaultValue,
                                                                                         EvaluationErrorKind.USER_NOT_SPECIFIED));
                    return(new EvaluationDetail <JToken>(defaultValue, null,
                                                         new EvaluationReason.Error(EvaluationErrorKind.USER_NOT_SPECIFIED)));
                }

                FeatureFlag.EvalResult evalResult = featureFlag.Evaluate(user, _featureStore, eventFactory);
                if (!IsOffline())
                {
                    foreach (var prereqEvent in evalResult.PrerequisiteEvents)
                    {
                        _eventProcessor.SendEvent(prereqEvent);
                    }
                }
                var detail = evalResult.Result;
                if (detail.VariationIndex == null)
                {
                    detail = new EvaluationDetail <JToken>(defaultValue, null, detail.Reason);
                }
                if (detail.Value != null && !CheckResultType(expectedType, detail.Value))
                {
                    Log.ErrorFormat("Expected type: {0} but got {1} when evaluating FeatureFlag: {2}. Returning default",
                                    expectedType,
                                    detail.Value.GetType(),
                                    featureKey);

                    _eventProcessor.SendEvent(eventFactory.NewDefaultFeatureRequestEvent(featureFlag, user, defaultValue,
                                                                                         EvaluationErrorKind.WRONG_TYPE));
                    return(new EvaluationDetail <JToken>(defaultValue, null,
                                                         new EvaluationReason.Error(EvaluationErrorKind.WRONG_TYPE)));
                }
                _eventProcessor.SendEvent(eventFactory.NewFeatureRequestEvent(featureFlag, user, detail, defaultValue));
                return(detail);
            }
            catch (Exception e)
            {
                Log.ErrorFormat("Encountered exception in LaunchDarkly client: {0} when evaluating feature key: {1} for user key: {2}",
                                Util.ExceptionMessage(e),
                                featureKey,
                                user.Key);
                Log.Debug(e.ToString(), e);
                var detail = new EvaluationDetail <JToken>(defaultValue, null,
                                                           new EvaluationReason.Error(EvaluationErrorKind.EXCEPTION));
                if (featureFlag == null)
                {
                    _eventProcessor.SendEvent(eventFactory.NewUnknownFeatureRequestEvent(featureKey, user, defaultValue,
                                                                                         EvaluationErrorKind.EXCEPTION));
                }
                else
                {
                    _eventProcessor.SendEvent(eventFactory.NewFeatureRequestEvent(featureFlag, user,
                                                                                  detail, defaultValue));
                }
                return(detail);
            }
        }
Esempio n. 10
0
 public T Get <T>(VersionedDataKind <T> kind, string key) where T : class, IVersionedData
 {
     return(_store.Get(kind, key));
 }