internal StreamProcessor(
            LdClientContext context,
            IDataSourceUpdates dataSourceUpdates,
            Uri baseUri,
            TimeSpan initialReconnectDelay,
            EventSourceCreator eventSourceCreator
            )
        {
            _log = context.Basic.Logger.SubLogger(LogNames.DataSourceSubLog);
            _log.Info("Connecting to LaunchDarkly stream");

            _dataSourceUpdates     = dataSourceUpdates;
            _httpConfig            = context.Http;
            _initialReconnectDelay = initialReconnectDelay;
            _diagnosticStore       = context.DiagnosticStore;
            _initTask  = new TaskCompletionSource <bool>();
            _streamUri = new Uri(baseUri, "/all");

            _storeStatusMonitoringEnabled = _dataSourceUpdates.DataStoreStatusProvider.StatusMonitoringEnabled;
            if (_storeStatusMonitoringEnabled)
            {
                _dataSourceUpdates.DataStoreStatusProvider.StatusChanged += OnDataStoreStatusChanged;
            }

            _es = (eventSourceCreator ?? CreateEventSource)(_streamUri, _httpConfig);
            _es.MessageReceived += OnMessage;
            _es.Error           += OnError;
            _es.Opened          += OnOpen;
        }
예제 #2
0
        internal LdClientContext(
            Configuration configuration,
            object eventSender,
            IDiagnosticStore diagnosticStore,
            IDiagnosticDisabler diagnosticDisabler
            )
        {
            this.Basic = new BasicConfiguration(configuration.MobileKey);

            var logConfig = (configuration.LoggingConfigurationBuilder ?? Components.Logging())
                            .CreateLoggingConfiguration();
            var logAdapter = logConfig.LogAdapter ?? Logs.None;

            this.BaseLogger = logAdapter.Logger(logConfig.BaseLoggerName ?? LogNames.Base);

            this.EnableBackgroundUpdating = configuration.EnableBackgroundUpdating;
            this.EvaluationReasons        = configuration.EvaluationReasons;
            this.Http = (configuration.HttpConfigurationBuilder ?? Components.HttpConfiguration())
                        .CreateHttpConfiguration(this.Basic);
            this.ServiceEndpoints = configuration.ServiceEndpoints;

            this.DiagnosticStore    = diagnosticStore;
            this.DiagnosticDisabler = diagnosticDisabler;
            this.TaskExecutor       = new TaskExecutor(
                eventSender,
                PlatformSpecific.AsyncScheduler.ScheduleAction,
                this.BaseLogger
                );
        }
예제 #3
0
        internal EventProcessorInternal(
            EventsConfiguration config,
            BlockingCollection <IEventMessage> messageQueue,
            IEventSender eventSender,
            IUserDeduplicator userDeduplicator,
            IDiagnosticStore diagnosticStore,
            Logger logger,
            Action testActionOnDiagnosticSend
            )
        {
            _config                     = config;
            _diagnosticStore            = diagnosticStore;
            _userDeduplicator           = userDeduplicator;
            _testActionOnDiagnosticSend = testActionOnDiagnosticSend;
            _flushWorkersCounter        = new CountdownEvent(1);
            _eventSender                = eventSender;
            _logger                     = logger;
            _random                     = new Random();

            EventBuffer buffer = new EventBuffer(config.EventCapacity > 0 ? config.EventCapacity : 1, _diagnosticStore, _logger);

            // Here we use TaskFactory.StartNew instead of Task.Run() because that allows us to specify the
            // LongRunning option. This option tells the task scheduler that the task is likely to hang on
            // to a thread for a long time, so it should consider growing the thread pool.
            Task.Factory.StartNew(
                () => RunMainLoop(messageQueue, buffer),
                TaskCreationOptions.LongRunning
                );
        }
예제 #4
0
        public void DiagnosticStorePassedToFactoriesWhenSupported()
        {
            var epfwd  = new Mock <IEventProcessorFactoryWithDiagnostics>();
            var upfwd  = new Mock <IUpdateProcessorFactoryWithDiagnostics>();
            var config = Configuration.Builder("SDK_KEY")
                         .IsStreamingEnabled(false)
                         .BaseUri(new Uri("http://fake"))
                         .StartWaitTime(TimeSpan.Zero)
                         .EventProcessorFactory(epfwd.Object)
                         .UpdateProcessorFactory(upfwd.Object)
                         .Build();

            IDiagnosticStore eventProcessorDiagnosticStore  = null;
            IDiagnosticStore updateProcessorDiagnosticStore = null;

            epfwd.Setup(epf => epf.CreateEventProcessor(config, It.IsAny <IDiagnosticStore>()))
            .Callback <Configuration, IDiagnosticStore>((c, ds) => eventProcessorDiagnosticStore = ds)
            .Returns(Components.NullEventProcessor.CreateEventProcessor(config));
            upfwd.Setup(upf => upf.CreateUpdateProcessor(config, It.IsAny <IFeatureStore>(), It.IsAny <IDiagnosticStore>()))
            .Callback <Configuration, IFeatureStore, IDiagnosticStore>((c, fs, ds) => updateProcessorDiagnosticStore = ds)
            .Returns(updateProcessor);

            using (var client = new LdClient(config))
            {
                epfwd.Verify(epf => epf.CreateEventProcessor(config, It.IsNotNull <IDiagnosticStore>()), Times.Once());
                epfwd.VerifyNoOtherCalls();
                upfwd.Verify(upf => upf.CreateUpdateProcessor(config, It.IsNotNull <IFeatureStore>(), It.IsNotNull <IDiagnosticStore>()), Times.Once());
                upfwd.VerifyNoOtherCalls();
                Assert.True(eventProcessorDiagnosticStore == updateProcessorDiagnosticStore);
            }
        }
        public void PersistedEventIsNull()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();
            var persistedEvent = _serverDiagnosticStore.PersistedUnsentEvent;

            Assert.Null(persistedEvent);
        }
예제 #6
0
        public void DiagnosticStoreNotPassedToFactoriesWhenOptedOut()
        {
            var epf    = new Mock <IEventProcessorFactory>();
            var dsf    = new Mock <IDataSourceFactory>();
            var config = BasicConfig()
                         .Events(epf.Object)
                         .DataSource(dsf.Object)
                         .DiagnosticOptOut(true)
                         .Build();

            IDiagnosticStore eventProcessorDiagnosticStore = null;
            IDiagnosticStore dataSourceDiagnosticStore     = null;
            var dataSource = MockDataSourceWithStartFn(_ => Task.FromResult(true));

            epf.Setup(f => f.CreateEventProcessor(It.IsAny <LdClientContext>()))
            .Callback((LdClientContext ctx) => eventProcessorDiagnosticStore = ctx.DiagnosticStore)
            .Returns(new ComponentsImpl.NullEventProcessor());
            dsf.Setup(f => f.CreateDataSource(It.IsAny <LdClientContext>(), It.IsAny <IDataSourceUpdates>()))
            .Callback((LdClientContext ctx, IDataSourceUpdates dsu) => dataSourceDiagnosticStore = ctx.DiagnosticStore)
            .Returns((LdClientContext ctx, IDataSourceUpdates dsu) => dataSource);

            using (var client = new LdClient(config))
            {
                epf.Verify(f => f.CreateEventProcessor(It.IsNotNull <LdClientContext>()), Times.Once());
                epf.VerifyNoOtherCalls();
                dsf.Verify(f => f.CreateDataSource(It.IsNotNull <LdClientContext>(), It.IsNotNull <IDataSourceUpdates>()), Times.Once());
                dsf.VerifyNoOtherCalls();
                Assert.Null(eventProcessorDiagnosticStore);
                Assert.Null(dataSourceDiagnosticStore);
            }
        }
        public void DiagnosticStoreNotPassedToFactoriesWhenOptedOut()
        {
            var epf    = new Mock <IEventProcessorFactory>();
            var dsf    = new Mock <IDataSourceFactory>();
            var config = Configuration.Builder(sdkKey)
                         .DataSource(Components.ExternalUpdatesOnly)
                         .StartWaitTime(TimeSpan.Zero)
                         .Events(epf.Object)
                         .DataSource(dsf.Object)
                         .DiagnosticOptOut(true)
                         .Logging(Components.Logging(testLogging))
                         .Build();

            IDiagnosticStore eventProcessorDiagnosticStore = null;
            IDiagnosticStore dataSourceDiagnosticStore     = null;

            epf.Setup(f => f.CreateEventProcessor(It.IsAny <LdClientContext>()))
            .Callback((LdClientContext ctx) => eventProcessorDiagnosticStore = ctx.DiagnosticStore)
            .Returns(new ComponentsImpl.NullEventProcessor());
            dsf.Setup(f => f.CreateDataSource(It.IsAny <LdClientContext>(), It.IsAny <IDataSourceUpdates>()))
            .Callback((LdClientContext ctx, IDataSourceUpdates dsu) => dataSourceDiagnosticStore = ctx.DiagnosticStore)
            .Returns((LdClientContext ctx, IDataSourceUpdates dsu) => dataSource);

            using (var client = new LdClient(config))
            {
                epf.Verify(f => f.CreateEventProcessor(It.IsNotNull <LdClientContext>()), Times.Once());
                epf.VerifyNoOtherCalls();
                dsf.Verify(f => f.CreateDataSource(It.IsNotNull <LdClientContext>(), It.IsNotNull <IDataSourceUpdates>()), Times.Once());
                dsf.VerifyNoOtherCalls();
                Assert.Null(eventProcessorDiagnosticStore);
                Assert.Null(dataSourceDiagnosticStore);
            }
        }
예제 #8
0
        public void DataSinceFromLastDiagnostic()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore(null);
            DiagnosticEvent  periodicEvent          = _serverDiagnosticStore.CreateEventAndReset();

            Assert.Equal(periodicEvent.JsonValue.Get("creationDate").AsLong,
                         UnixMillisecondTime.FromDateTime(_serverDiagnosticStore.DataSince).Value);
        }
예제 #9
0
 internal EventBuffer(int capacity, IDiagnosticStore diagnosticStore, Logger logger)
 {
     _capacity        = capacity;
     _events          = new List <object>();
     _summarizer      = new EventSummarizer();
     _diagnosticStore = diagnosticStore;
     _logger          = logger;
 }
        public void DataSinceFromLastDiagnostic()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();
            DiagnosticEvent  periodicEvent          = _serverDiagnosticStore.CreateEventAndReset();

            Assert.Equal(periodicEvent.JsonValue.Get("creationDate").AsLong,
                         Util.GetUnixTimestampMillis(_serverDiagnosticStore.DataSince));
        }
        public void CanIncrementDroppedEvents()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();

            _serverDiagnosticStore.IncrementDroppedEvents();
            DiagnosticEvent periodicEvent = _serverDiagnosticStore.CreateEventAndReset();

            Assert.Equal(1, periodicEvent.JsonValue.Get("droppedEvents").AsInt);
        }
        public void CanRecordEventsInBatch()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();

            _serverDiagnosticStore.RecordEventsInBatch(4);
            DiagnosticEvent periodicEvent = _serverDiagnosticStore.CreateEventAndReset();

            Assert.Equal(4, periodicEvent.JsonValue.Get("eventsInLastBatch").AsInt);
        }
예제 #13
0
        public void CanIncrementDeduplicateUsers()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore(null);

            _serverDiagnosticStore.IncrementDeduplicatedUsers();
            DiagnosticEvent periodicEvent = _serverDiagnosticStore.CreateEventAndReset();

            Assert.Equal(1, periodicEvent.JsonValue.Get("deduplicatedUsers").AsInt);
        }
        private IDataSource MakeDataSourceWithDiagnostics(Uri baseUri, User user, IDiagnosticStore diagnosticStore)
        {
            var config = BasicConfig()
                         .ServiceEndpoints(Components.ServiceEndpoints().Streaming(baseUri).Polling(baseUri))
                         .Build();
            var context = new LdClientContext(config, null, diagnosticStore, null);

            return(Components.StreamingDataSource().InitialReconnectDelay(BriefReconnectDelay)
                   .CreateDataSource(context, _updateSink, user, false));
        }
        public void PeriodicEventUsesIdFromInit()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();
            DiagnosticEvent? initEvent = _serverDiagnosticStore.InitEvent;

            Assert.True(initEvent.HasValue);
            DiagnosticEvent periodicEvent = _serverDiagnosticStore.CreateEventAndReset();

            Assert.Equal(initEvent.Value.JsonValue.Get("id"), periodicEvent.JsonValue.Get("id"));
        }
        public EventProcessor(
            EventsConfiguration config,
            IEventSender eventSender,
            IUserDeduplicator userDeduplicator,
            IDiagnosticStore diagnosticStore,
            IDiagnosticDisabler diagnosticDisabler,
            Logger logger,
            Action testActionOnDiagnosticSend
            )
        {
            _logger  = logger;
            _stopped = new AtomicBoolean(false);
            _offline = new AtomicBoolean(false);
            _sentInitialDiagnostics = new AtomicBoolean(false);
            _inputCapacityExceeded  = new AtomicBoolean(false);
            _messageQueue           = new BlockingCollection <EventProcessorInternal.IEventMessage>(
                config.EventCapacity > 0 ? config.EventCapacity : 1);

            _processorInternal = new EventProcessorInternal(
                config,
                _messageQueue,
                eventSender,
                userDeduplicator,
                diagnosticStore,
                _logger,
                testActionOnDiagnosticSend
                );

            if (config.EventFlushInterval > TimeSpan.Zero)
            {
                _flushTimer = new Timer(DoBackgroundFlush, null, config.EventFlushInterval,
                                        config.EventFlushInterval);
            }
            _diagnosticStore             = diagnosticStore;
            _diagnosticRecordingInterval = config.DiagnosticRecordingInterval;
            if (userDeduplicator != null && userDeduplicator.FlushInterval.HasValue)
            {
                _flushUsersTimer = new Timer(DoUserKeysFlush, null, userDeduplicator.FlushInterval.Value,
                                             userDeduplicator.FlushInterval.Value);
            }
            else
            {
                _flushUsersTimer = null;
            }

            if (diagnosticStore != null)
            {
                SetupDiagnosticInit(diagnosticDisabler == null || !diagnosticDisabler.Disabled);

                if (diagnosticDisabler != null)
                {
                    diagnosticDisabler.DisabledChanged += ((sender, args) => SetupDiagnosticInit(!args.Disabled));
                }
            }
        }
 internal LdClientContext(
     BasicConfiguration basic,
     HttpConfiguration http,
     IDiagnosticStore diagnosticStore,
     TaskExecutor taskExecutor
     )
 {
     Basic           = basic;
     Http            = http;
     DiagnosticStore = diagnosticStore;
     TaskExecutor    = taskExecutor;
 }
        public void InitEventFieldsAreCorrect()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();

            Assert.NotNull(_serverDiagnosticStore.InitEvent);
            LdValue initEvent = _serverDiagnosticStore.InitEvent.Value.JsonValue;

            Assert.Equal("diagnostic-init", initEvent.Get("kind").AsString);
            Assert.Equal(_expectedPlatform, initEvent.Get("platform"));
            Assert.Equal(_expectedSdk, initEvent.Get("sdk"));
            Assert.Equal(_expectedConfig, initEvent.Get("configuration"));
            Assert.Equal("DK_KEY", initEvent.Get("id").Get("sdkKeySuffix").AsString);
            Assert.Equal(Util.GetUnixTimestampMillis(_serverDiagnosticStore.DataSince), initEvent.Get("creationDate").AsLong);
        }
예제 #19
0
 public IEventProcessor CreateEventProcessor(Configuration config, IDiagnosticStore diagnosticStore)
 {
     if (config.Offline)
     {
         return(new NullEventProcessor());
     }
     else
     {
         return(new DefaultEventProcessor(config.EventProcessorConfiguration,
                                          new DefaultUserDeduplicator(config),
                                          Util.MakeHttpClient(config.HttpRequestConfiguration, ServerSideClientEnvironment.Instance),
                                          diagnosticStore, null, null));
     }
 }
        public void PeriodicEventDefaultValuesAreCorrect()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();
            DateTime         dataSince     = _serverDiagnosticStore.DataSince;
            LdValue          periodicEvent = _serverDiagnosticStore.CreateEventAndReset().JsonValue;

            Assert.Equal("diagnostic", periodicEvent.Get("kind").AsString);
            Assert.Equal(Util.GetUnixTimestampMillis(dataSince), periodicEvent.Get("dataSinceDate").AsLong);
            Assert.Equal(0, periodicEvent.Get("eventsInLastBatch").AsInt);
            Assert.Equal(0, periodicEvent.Get("droppedEvents").AsInt);
            Assert.Equal(0, periodicEvent.Get("deduplicatedUsers").AsInt);

            LdValue streamInits = periodicEvent.Get("streamInits");

            Assert.Equal(0, streamInits.Count);
        }
        public void CanAddStreamInit()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();
            DateTime         timestamp = DateTime.Now;

            _serverDiagnosticStore.AddStreamInit(timestamp, TimeSpan.FromMilliseconds(200.0), true);
            DiagnosticEvent periodicEvent = _serverDiagnosticStore.CreateEventAndReset();

            LdValue streamInits = periodicEvent.JsonValue.Get("streamInits");

            Assert.Equal(1, streamInits.Count);

            LdValue streamInit = streamInits.Get(0);

            Assert.Equal(Util.GetUnixTimestampMillis(timestamp), streamInit.Get("timestamp").AsLong);
            Assert.Equal(200, streamInit.Get("durationMillis").AsInt);
            Assert.Equal(true, streamInit.Get("failed").AsBool);
        }
        public void CreatingEventResetsFields()
        {
            IDiagnosticStore _serverDiagnosticStore = CreateDiagnosticStore();

            _serverDiagnosticStore.IncrementDroppedEvents();
            _serverDiagnosticStore.IncrementDeduplicatedUsers();
            _serverDiagnosticStore.RecordEventsInBatch(10);
            _serverDiagnosticStore.AddStreamInit(DateTime.Now, TimeSpan.FromMilliseconds(200.0), true);
            LdValue firstPeriodicEvent = _serverDiagnosticStore.CreateEventAndReset().JsonValue;
            LdValue nextPeriodicEvent  = _serverDiagnosticStore.CreateEventAndReset().JsonValue;

            Assert.Equal(firstPeriodicEvent.Get("creationDate"), nextPeriodicEvent.Get("dataSinceDate"));
            Assert.Equal(0, nextPeriodicEvent.Get("eventsInLastBatch").AsInt);
            Assert.Equal(0, nextPeriodicEvent.Get("droppedEvents").AsInt);
            Assert.Equal(0, nextPeriodicEvent.Get("deduplicatedUsers").AsInt);
            Assert.Equal(0, nextPeriodicEvent.Get("eventsInLastBatch").AsInt);
            LdValue streamInits = nextPeriodicEvent.Get("streamInits");

            Assert.Equal(0, streamInits.Count);
        }
예제 #23
0
        internal DateTime _esStarted; // exposed for testing

        internal StreamingDataSource(
            IDataSourceUpdateSink updateSink,
            User user,
            Uri baseUri,
            bool withReasons,
            TimeSpan initialReconnectDelay,
            IFeatureFlagRequestor requestor,
            HttpConfiguration httpConfig,
            Logger log,
            IDiagnosticStore diagnosticStore
            )
        {
            this._updateSink            = updateSink;
            this._user                  = user;
            this._baseUri               = baseUri;
            this._useReport             = httpConfig.UseReport;
            this._withReasons           = withReasons;
            this._initialReconnectDelay = initialReconnectDelay;
            this._requestor             = requestor;
            this._httpProperties        = httpConfig.HttpProperties;
            this._diagnosticStore       = diagnosticStore;
            this._initTask              = new TaskCompletionSource <bool>();
            this._log = log;
        }
 private EventProcessor MakeProcessor(EventsConfiguration config, Mock <IEventSender> mockSender,
                                      IDiagnosticStore diagnosticStore, IDiagnosticDisabler diagnosticDisabler, CountdownEvent diagnosticCountdown)
 {
     return(new EventProcessor(config, mockSender.Object, new TestUserDeduplicator(),
                               diagnosticStore, diagnosticDisabler, NullLogger, () => { diagnosticCountdown.Signal(); }));
 }
예제 #25
0
 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));
         }
     }
 }
예제 #26
0
 internal StreamProcessor(Configuration config, IFeatureRequestor featureRequestor,
                          IFeatureStore featureStore, StreamManager.EventSourceCreator eventSourceCreator, IDiagnosticStore diagnosticStore)
 {
     _streamManager = new StreamManager(this,
                                        MakeStreamProperties(config),
                                        config.StreamManagerConfiguration,
                                        ServerSideClientEnvironment.Instance,
                                        eventSourceCreator, diagnosticStore);
     _config           = config;
     _featureRequestor = featureRequestor;
     _featureStore     = featureStore;
 }