internal EvalResult Evaluate(User user, IFeatureStore featureStore, EventFactory eventFactory) { IList <FeatureRequestEvent> prereqEvents = new List <FeatureRequestEvent>(); EvalResult evalResult = new EvalResult(null, null, prereqEvents); if (user == null || user.Key == null) { Log.WarnFormat("User or user key is null when evaluating flag: {0} returning null", Key); return(evalResult); } if (On) { evalResult = Evaluate(user, featureStore, prereqEvents, eventFactory); if (evalResult.Result != null) { return(evalResult); } } evalResult.Variation = OffVariation; evalResult.Result = OffVariationValue; return(evalResult); }
internal PollingProcessor(Configuration config, FeatureRequestor featureRequestor, IFeatureStore featureStore) { _config = config; _featureRequestor = featureRequestor; _featureStore = featureStore; _initTask = new TaskCompletionSource <bool>(); }
public IUpdateProcessor CreateUpdateProcessor(Configuration config, IFeatureStore featureStore, IDiagnosticStore diagnosticStore) { if (config.Offline) { Log.Info("Starting Launchdarkly client in offline mode."); return(new NullUpdateProcessor()); } else if (config.UseLdd) { Log.Info("Starting LaunchDarkly in LDD mode. Skipping direct feature retrieval."); return(new NullUpdateProcessor()); } else { FeatureRequestor requestor = new FeatureRequestor(config); if (config.IsStreamingEnabled) { return(new StreamProcessor(config, requestor, featureStore, null, diagnosticStore)); } else { Log.Warn("You should only disable the streaming API if instructed to do so by LaunchDarkly support"); return(new PollingProcessor(config, requestor, featureStore)); } } }
private int?EvaluateIndex(User user, IFeatureStore store) { // Check to see if targets match foreach (var target in Targets) { foreach (var v in target.Values) { if (v.Equals(user.Key)) { return(target.Variation); } } } // Now walk through the rules and see if any match foreach (Rule rule in Rules) { if (rule.MatchesUser(user, store)) { return(rule.VariationIndexForUser(user, Key, Salt)); } } // Walk through the fallthrough and see if it matches return(Fallthrough.VariationIndexForUser(user, Key, Salt)); }
public FileDataSource(IFeatureStore featureStore, List <string> paths, bool autoUpdate, TimeSpan pollInterval, Func <string, object> alternateParser) { _featureStore = featureStore; _paths = new List <string>(paths); _parser = new FlagFileParser(alternateParser); if (autoUpdate) { try { #if NETSTANDARD1_4 || NETSTANDARD1_6 _reloader = new FilePollingReloader(_paths, TriggerReload, pollInterval); #else _reloader = new FileWatchingReloader(_paths, TriggerReload); #endif } catch (Exception e) { Log.ErrorFormat("Unable to watch files for auto-updating: {0}", e); _reloader = null; } } else { _reloader = null; } }
public ClientFeatureValueProvider( IFeatureStore featureStore, ICurrentClient currentClient) : base(featureStore) { CurrentClient = currentClient; }
public ConfigurationBuilder(Configuration copyFrom) { _allAttributesPrivate = copyFrom.AllAttributesPrivate; _baseUri = copyFrom.BaseUri; _diagnosticOptOut = copyFrom.DiagnosticOptOut; _diagnosticRecordingInterval = copyFrom.DiagnosticRecordingInterval; _eventCapacity = copyFrom.EventCapacity; _eventFlushInterval = copyFrom.EventFlushInterval; _eventProcessorFactory = copyFrom.EventProcessorFactory; #pragma warning disable 618 _eventSamplingInterval = copyFrom.EventSamplingInterval; #pragma warning restore 618 _eventsUri = copyFrom.EventsUri; _featureStore = copyFrom.FeatureStore; _featureStoreFactory = copyFrom.FeatureStoreFactory; _httpClientHandler = copyFrom.HttpClientHandler; _httpClientTimeout = copyFrom.HttpClientTimeout; _inlineUsersInEvents = copyFrom.InlineUsersInEvents; _isStreamingEnabled = copyFrom.IsStreamingEnabled; _offline = copyFrom.Offline; _pollingInterval = copyFrom.PollingInterval; _privateAttributeNames = copyFrom.PrivateAttributeNames is null ? null : new HashSet <string>(copyFrom.PrivateAttributeNames); _readTimeout = copyFrom.ReadTimeout; _reconnectTime = copyFrom.ReconnectTime; _sdkKey = copyFrom.SdkKey; _startWaitTime = copyFrom.StartWaitTime; _streamUri = copyFrom.StreamUri; _updateProcessorFactory = copyFrom.UpdateProcessorFactory; _useLdd = copyFrom.UseLdd; _userKeysCapacity = copyFrom.UserKeysCapacity; _userKeysFlushInterval = copyFrom.UserKeysFlushInterval; _wrapperName = copyFrom.WrapperName; _wrapperVersion = copyFrom.WrapperVersion; }
protected NewsViewModel(IMvxNavigationService navigation , IMvxMessenger messenger , INewsService news , IReachabilityService reachability , IFeatureStore featureStore , IBrowserService browser , IDialogService dialog) { _navigation = navigation; _messenger = messenger; _news = news; _reachability = reachability; _featureStore = featureStore; _browser = browser; _dialog = dialog; _stories = new MvxObservableCollection <StoryItemViewModel>(); ShowStoryCommand = new MvxAsyncCommand <StoryItemViewModel>(OnShowStory, item => item.Filled && item.Story.Type == ItemType.Story); RefreshCommand = new MvxAsyncCommand(LoadStories); ShowSettingsCommand = new MvxAsyncCommand(() => _navigation.Navigate <SettingsViewModel>()); _fillerToken = messenger.Subscribe <NewsItemMessage>(OnItemReceived); TabPresentation = featureStore.IsEnabled(Features.StoryTabPresentation); }
/// <summary> /// Creates a new client to connect to LaunchDarkly with a custom configuration, and a custom /// implementation of the analytics event processor. This constructor should only be used if you are /// overriding the default event-sending behavior. /// </summary> /// <param name="config">a client configuration object</param> /// <param name="eventStore">an event processor</param> public LdClient(Configuration config, IStoreEvents eventStore) { Log.InfoFormat("Starting LaunchDarkly Client {0}", Configuration.Version); _configuration = config; _eventStore = eventStore; _featureStore = _configuration.FeatureStore; if (_configuration.Offline) { Log.Info("Starting Launchdarkly client in offline mode."); return; } var featureRequestor = new FeatureRequestor(config); if (_configuration.IsStreamingEnabled) { _updateProcessor = new StreamProcessor(config, featureRequestor, _featureStore); } else { Log.Warn("You should only disable the streaming API if instructed to do so by LaunchDarkly support"); _updateProcessor = new PollingProcessor(config, featureRequestor, _featureStore); } var initTask = _updateProcessor.Start(); Log.InfoFormat("Waiting up to {0} milliseconds for LaunchDarkly client to start..", _configuration.StartWaitTime.TotalMilliseconds); var unused = initTask.Wait(_configuration.StartWaitTime); }
public MockNewsViewModel(IMvxNavigationService navigation , IMvxMessenger messenger , INewsService news , IReachabilityService reachability , IFeatureStore featureStore , IBrowserService browser , IDialogService dialog) : base(navigation, messenger, news, reachability, featureStore, browser, dialog) =>
internal StreamProcessor(Configuration config, IFeatureRequestor featureRequestor, IFeatureStore featureStore) { _config = config; _featureRequestor = featureRequestor; _featureStore = featureStore; _initTask = new TaskCompletionSource <bool>(); _backOff = new EventSource.ExponentialBackoffWithDecorrelation(_config.ReconnectTime, TimeSpan.FromMilliseconds(30000)); }
public LdClient(Configuration config, IEventProcessor eventProcessor) { Log.InfoFormat("Starting LaunchDarkly Client {0}", ServerSideClientEnvironment.Instance.Version); _configuration = config; if (eventProcessor == null) { _eventProcessor = (_configuration.EventProcessorFactory ?? Components.DefaultEventProcessor).CreateEventProcessor(_configuration); _shouldDisposeEventProcessor = true; } else { _eventProcessor = eventProcessor; // The following line is for backward compatibility with the obsolete mechanism by which the // caller could pass in an IStoreEvents implementation instance that we did not create. We // were not disposing of that instance when the client was closed, so we should continue not // doing so until the next major version eliminates that mechanism. We will always dispose // of instances that we created ourselves from a factory. _shouldDisposeEventProcessor = false; } if (_configuration.FeatureStore == null) { _featureStore = (_configuration.FeatureStoreFactory ?? Components.InMemoryFeatureStore).CreateFeatureStore(); _shouldDisposeFeatureStore = true; } else { _featureStore = _configuration.FeatureStore; _shouldDisposeFeatureStore = false; // see previous comment } _updateProcessor = (_configuration.UpdateProcessorFactory ?? Components.DefaultUpdateProcessor).CreateUpdateProcessor(_configuration, _featureStore); var initTask = _updateProcessor.Start(); if (!(_updateProcessor is NullUpdateProcessor)) { Log.InfoFormat("Waiting up to {0} milliseconds for LaunchDarkly client to start..", _configuration.StartWaitTime.TotalMilliseconds); } try { var unused = initTask.Wait(_configuration.StartWaitTime); } catch (AggregateException) { // StreamProcessor may throw an exception if initialization fails, because we want that behavior // in the Xamarin client. However, for backward compatibility we do not want to throw exceptions // from the LdClient constructor in the .NET client, so we'll just swallow this. } }
private LdClient MakeClient(IFeatureStore featureStore, MockEventProcessor ep) { Configuration config = Configuration.Default("secret") .WithFeatureStoreFactory(TestUtils.SpecificFeatureStore(featureStore)) .WithEventProcessorFactory(TestUtils.SpecificEventProcessor(ep)) .WithUpdateProcessorFactory(Components.NullUpdateProcessor); LdClient client = new LdClient(config); featureStore.Init(new Dictionary <IVersionedDataKind, IDictionary <string, IVersionedData> >()); return(client); }
// 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)); }
public SettingsViewModel(IMvxNavigationService navigation, IBrowserService browser, IAppService app, IFeatureStore features) { _navigation = navigation; _browser = browser; _features = features; ShowProjectSiteCommand = new MvxAsyncCommand(OnShowProjectSite); ShowLicensesCommand = new MvxAsyncCommand(OnShowLicenses); ShowFeatureTogglesCommand = new MvxAsyncCommand(OnShowFeatureToggles, () => features.IsEnabled(Features.ShowOverrideUi)); VersionString = $"{app.Name} for {app.Platform} v{app.Version} ({app.BuildNumber})"; }
internal bool MatchesUser(User user, IFeatureStore store) { foreach (var c in Clauses) { if (!c.MatchesUser(user, store)) { return(false); } } return(true); }
internal StreamProcessor(Configuration config, IFeatureRequestor featureRequestor, IFeatureStore featureStore, StreamManager.EventSourceCreator eventSourceCreator) { _streamManager = new StreamManager(this, MakeStreamProperties(config), config, ServerSideClientEnvironment.Instance, eventSourceCreator); _config = config; _featureRequestor = featureRequestor; _featureStore = featureStore; }
// 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); }
private Action MakeConcurrentModifier(IFeatureStore store, string key, params int[] versionsToWrite) { var i = 0; return(() => { if (i < versionsToWrite.Length) { store.Upsert(TestEntity.Kind, new TestEntity(key, versionsToWrite[i])); i++; } }); }
public void Setup() { var n = new NameValueCollection(); n.Add("features.FeatureA", "true"); n.Add("features.FeatureB", "True"); n.Add("features.FeatureC", "false"); n.Add("features.FeatureD", "False"); n.Add("features.FeatureE", "1"); n.Add("features.FeatureF", "0"); n.Add("features.FeatureG", "abc"); n.Add("features.FeatureH", "on"); n.Add("features.FeatureI", "yes"); globalFeatureStore = new CachingFeatureStore(new AppSettingsFeatureStore(n)); }
public async Task Setup() { StartZooKeeper(); var zk = new ZooKeeper("127.0.0.1:2181", 60000, null); await DeleteRecursive(zk, "/FeatureFlags", "features"); await CreateIfNotExist(zk, "/FeatureFlags/features/featureA", "true"); await CreateIfNotExist(zk, "/FeatureFlags/features/featureB", "false"); await CreateIfNotExist(zk, "/FeatureFlags/features/featureC", "true"); await CreateIfNotExist(zk, "/FeatureFlags/features/featureD", "true"); await zk.closeAsync(); featureStore = new CachingFeatureStore(new ZooKeeperFeatureStore("127.0.0.1:2181/FeatureFlags")); }
// 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 EvalResult Evaluate(User user, IFeatureStore featureStore, EventFactory eventFactory) { IList <FeatureRequestEvent> prereqEvents = new List <FeatureRequestEvent>(); if (user == null || user.Key == null) { Log.WarnFormat("User or user key is null when evaluating flag: {0} returning null", Key); return(new EvalResult( new EvaluationDetail <JToken>(null, null, new EvaluationReason.Error(EvaluationErrorKind.USER_NOT_SPECIFIED)), prereqEvents)); } var details = Evaluate(user, featureStore, prereqEvents, eventFactory); return(new EvalResult(details, prereqEvents)); }
private EvaluationDetail <JToken> Evaluate(User user, IFeatureStore featureStore, IList <FeatureRequestEvent> events, EventFactory eventFactory) { if (!On) { return(GetOffValue(EvaluationReason.Off.Instance)); } var prereqFailureReason = CheckPrerequisites(user, featureStore, events, eventFactory); if (prereqFailureReason != null) { return(GetOffValue(prereqFailureReason)); } // Check to see if targets match if (Targets != null) { foreach (var target in Targets) { foreach (var v in target.Values) { if (user.Key == v) { return(GetVariation(target.Variation, EvaluationReason.TargetMatch.Instance)); } } } } // Now walk through the rules and see if any match if (Rules != null) { for (int i = 0; i < Rules.Count; i++) { Rule rule = Rules[i]; if (rule.MatchesUser(user, featureStore)) { return(GetValueForVariationOrRollout(rule, user, new EvaluationReason.RuleMatch(i, rule.Id))); } } } // Walk through the fallthrough and see if it matches return(GetValueForVariationOrRollout(Fallthrough, user, EvaluationReason.Fallthrough.Instance)); }
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)); } }
public LdClient(Configuration config, IStoreEvents eventStore) { Logger.LogInformation("Starting LaunchDarkly Client " + Configuration.Version); _configuration = config; _eventStore = eventStore; _featureStore = config.FeatureStore; if (_configuration.Offline) { Logger.LogInformation("Starting Launchdarkly client in offline mode."); return; } var featureRequestor = new FeatureRequestor(config); _updateProcessor = new PollingProcessor(config, featureRequestor, _featureStore); var initTask = _updateProcessor.Start(); Logger.LogInformation("Waiting up to " + _configuration.StartWaitTime.TotalMilliseconds + " milliseconds for LaunchDarkly client to start.."); var unused = initTask.Task.Wait(_configuration.StartWaitTime); }
internal EvalResult Evaluate(User user, IFeatureStore featureStore) { IList <FeatureRequestEvent> prereqEvents = new List <FeatureRequestEvent>(); EvalResult evalResult = new EvalResult(null, prereqEvents); if (user == null || user.Key == null) { Logger.LogWarning("User or user key is null when evaluating flag: " + Key + " returning null"); return(evalResult); } if (On) { evalResult.Result = Evaluate(user, featureStore, prereqEvents); if (evalResult.Result != null) { return(evalResult); } } evalResult.Result = OffVariationValue; return(evalResult); }
// 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); }
public EditionFeatureValueProvider(IFeatureStore featureStore, ICurrentPrincipalAccessor principalAccessor) : base(featureStore) { PrincipalAccessor = principalAccessor; }
public DefaultValueFeatureValueProvider(IFeatureStore settingStore) : base(settingStore) { }