protected BucketedRollingCounterStream(IHystrixEventStream <Event> stream, int numBuckets, int bucketSizeInMs, Func <Bucket, Event, Bucket> appendRawEventToBucket, Func <Output, Bucket, Output> reduceBucket)
            : base(stream, numBuckets, bucketSizeInMs, appendRawEventToBucket)
        {
            Func <IObservable <Bucket>, IObservable <Output> > reduceWindowToSummary = (window) =>
            {
                var result = window.Aggregate(EmptyOutputValue, (arg1, arg2) => reduceBucket(arg1, arg2)).Select(n => n);
                return(result);
            };

            counterSubject = new BehaviorSubject <Output>(EmptyOutputValue);
            _sourceStream  = bucketedStream         // stream broken up into buckets

                             .Window(numBuckets, 1) // emit overlapping windows of buckets

                             .FlatMap((w) =>
                                      reduceWindowToSummary(w)) // convert a window of bucket-summaries into a single summary

                             .OnSubscribe(() =>
            {
                _isSourceCurrentlySubscribed.Value = true;
            })
                             .OnDispose(() =>
            {
                _isSourceCurrentlySubscribed.Value = false;
            })
                             .Publish().RefCount();   // multiple subscribers should get same data
        }
        protected RollingDistributionStream(IHystrixEventStream <Event> stream, int numBuckets, int bucketSizeInMs, Func <LongHistogram, Event, LongHistogram> addValuesToBucket)
        {
            var emptyDistributionsToStart = new List <LongHistogram>();

            for (var i = 0; i < numBuckets; i++)
            {
                emptyDistributionsToStart.Add(CachedValuesHistogram.GetNewHistogram());
            }

            Func <IObservable <Event>, IObservable <LongHistogram> > reduceBucketToSingleDistribution = (bucket) =>
            {
                var result = bucket.Aggregate(CachedValuesHistogram.GetNewHistogram(), (arg1, arg2) => addValuesToBucket(arg1, arg2)).Select(n => n);
                return(result);
            };

            _rollingDistributionStream = stream
                                         .Observe()
                                         .Window(TimeSpan.FromMilliseconds(bucketSizeInMs), NewThreadScheduler.Default) // stream of unaggregated buckets
                                         .SelectMany((d) => reduceBucketToSingleDistribution(d))                        // stream of aggregated Histograms
                                         .StartWith(emptyDistributionsToStart)                                          // stream of aggregated Histograms that starts with n empty
                                         .Window(numBuckets, 1)                                                         // windowed stream: each OnNext is a stream of n Histograms
                                         .SelectMany((w) => ReduceWindowToSingleDistribution(w))                        // reduced stream: each OnNext is a single Histogram
                                         .Map((h) => CacheHistogramValues(h))                                           // convert to CachedValueHistogram (commonly-accessed values are cached)
                                         .Publish().RefCount();
        }
        protected BucketedCounterStream(IHystrixEventStream <Event> inputEventStream, int numBuckets, int bucketSizeInMs, Func <Bucket, Event, Bucket> appendRawEventToBucket)
        {
            this.numBuckets        = numBuckets;
            this.bucketSizeInMs    = bucketSizeInMs;
            _reduceBucketToSummary = (eventsObservable) =>
            {
                var result = eventsObservable.Aggregate(EmptyBucketSummary, (arg1, arg2) => appendRawEventToBucket(arg1, arg2)).Select(n => n);
                return(result);
            };

            IList <Bucket> emptyEventCountsToStart = new List <Bucket>();

            for (var i = 0; i < numBuckets; i++)
            {
                emptyEventCountsToStart.Add(EmptyBucketSummary);
            }

            bucketedStream = Observable.Defer(() =>
            {
                return(inputEventStream
                       .Observe()
                       .Window(TimeSpan.FromMilliseconds(bucketSizeInMs), NewThreadScheduler.Default) // bucket it by the counter window so we can emit to the next operator in time chunks, not on every OnNext
                       .SelectMany((b) =>
                {
                    return _reduceBucketToSummary(b);
                })
                       .StartWith(emptyEventCountsToStart));       // start it with empty arrays to make consumer logic as generic as possible (windows are always full)
            });
        }
 protected BucketedCumulativeCounterStream(IHystrixEventStream <Event> stream, int numBuckets, int bucketSizeInMs, Func <Bucket, Event, Bucket> reduceCommandCompletion, Func <Output, Bucket, Output> reduceBucket)
     : base(stream, numBuckets, bucketSizeInMs, reduceCommandCompletion)
 {
     this.counterSubject = new BehaviorSubject <Output>(EmptyOutputValue);
     this.sourceStream   = bucketedStream
                           .Scan(EmptyOutputValue, (arg1, arg2) => reduceBucket(arg1, arg2))
                           .Skip(numBuckets)
                           .OnSubscribe(() => { isSourceCurrentlySubscribed.Value = true; })
                           .OnDispose(() => { isSourceCurrentlySubscribed.Value = false; })
                           .Publish().RefCount(); // multiple subscribers should get same data
 }
        protected RollingConcurrencyStream(IHystrixEventStream <HystrixCommandExecutionStarted> inputEventStream, int numBuckets, int bucketSizeInMs)
        {
            List <int> emptyRollingMaxBuckets = new List <int>();

            for (int i = 0; i < numBuckets; i++)
            {
                emptyRollingMaxBuckets.Add(0);
            }

            rollingMaxStream = inputEventStream
                               .Observe()
                               .Map((arg) => GetConcurrencyCountFromEvent(arg))
                               .Window(TimeSpan.FromMilliseconds(bucketSizeInMs))
                               .SelectMany((arg) => ReduceStreamToMax(arg))
                               .StartWith(emptyRollingMaxBuckets)
                               .Window(numBuckets, 1)
                               .SelectMany((arg) => ReduceStreamToMax(arg))
                               .Publish().RefCount();
        }