public void GetExistingFeature() { InitStore(); var result = store.Get(VersionedDataKind.Features, feature1.Key); Assert.Equal(feature1.Key, result.Key); }
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); }
// 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)); }
// 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); }
// 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); }
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)); } }
// 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); }
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); }
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); } }
public T Get <T>(VersionedDataKind <T> kind, string key) where T : class, IVersionedData { return(_store.Get(kind, key)); }