예제 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="T:Wibblr.Metrics.Core.EventCollector"/> class.
        /// This particular constructor is internal as it contains a parameter for the IClock,
        /// which is only used during testing.
        /// </summary>
        /// <param name="sink">Sink.</param>
        /// <param name="clock">Clock.</param>
        /// <param name="windowSize">Resolution.</param>
        /// <param name="flushInterval">Flush interval.</param>
        internal MetricsCollector(IMetricsSink sink, IClock clock, TimeSpan windowSize, TimeSpan flushInterval, bool ignoreEmptyBuckets)
        {
            if (windowSize.TotalMilliseconds < 100)
            {
                throw new ArgumentException("Must be 100ms or greater", nameof(windowSize));
            }

            if (flushInterval.TotalMilliseconds < 200)
            {
                throw new ArgumentException("Must be 200ms or greater", nameof(flushInterval));
            }

            if (flushInterval < windowSize)
            {
                throw new ArgumentException("Cannot be less than the window size", nameof(flushInterval));
            }

            if (!windowSize.IsDivisorOf(TimeSpan.FromDays(1)))
            {
                throw new ArgumentException("Must be whole number of windows per day", nameof(windowSize));
            }

            this.sink               = sink;
            this.clock              = clock;
            this.windowSize         = windowSize;
            this.flushInterval      = flushInterval;
            this.ignoreEmptyBuckets = true;

            clock.SetDelayedAction(Flush);
            clock.ExecuteAfterDelay(flushInterval);
        }
예제 #2
0
        /// <summary>
        /// Flush this instance.
        /// </summary>
        private void Flush()
        {
            try
            {
                bool isFlushCancelled = clock.IsDelayedActionCancelled();
                var  tempCounters     = new List <WindowedCounter>();
                var  tempBuckets      = new List <WindowedBucket>();
                var  tempEvents       = new List <TimestampedEvent>();
                var  tempProfiles     = new List <Profile>();

                // Any events that are recorded after this line will have a start time equal
                // or later to this.
                var currentTimePeriodStart = clock.Current.RoundDown(windowSize);

                lock (countersLock)
                {
                    foreach (var c in counters.Keys.ToList())
                    {
                        // Only take counts before the current timeperiod (unless
                        // the delayedAction is cancelled, i.e. there will be no more flushes),
                        // so that each counter is only written once for each window.
                        if (isFlushCancelled || c.from < currentTimePeriodStart)
                        {
                            tempCounters.Add(new WindowedCounter
                            {
                                name  = c.name,
                                from  = c.from,
                                to    = c.to,
                                count = counters[c]
                            });
                            counters.Remove(c);
                        }
                    }
                }

                // Flush even if there are no events, so that any queued events
                // in the sink are flushed.
                if (tempCounters != null)
                {
                    sink.Flush(tempCounters);
                }

                lock (histogramsLock)
                {
                    foreach (var h in histograms.Keys.ToList())
                    {
                        if (isFlushCancelled || h.from < currentTimePeriodStart)
                        {
                            foreach (var bucket in histograms[h].Buckets())
                            {
                                if (ignoreEmptyBuckets && bucket.count == 0)
                                {
                                    continue;
                                }

                                tempBuckets.Add(new WindowedBucket
                                {
                                    name      = h.name,
                                    timeFrom  = h.from,
                                    timeTo    = h.to,
                                    valueFrom = bucket.from,
                                    valueTo   = bucket.to,
                                    count     = bucket.count
                                });
                            }
                            histograms.Remove(h);
                        }
                    }
                }
                if (tempBuckets != null)
                {
                    sink.Flush(tempBuckets);
                }

                lock (eventsLock)
                {
                    foreach (var name in events.Keys)
                    {
                        foreach (var timestamp in events[name])
                        {
                            tempEvents.Add(new TimestampedEvent
                            {
                                name      = name,
                                timestamp = timestamp
                            });
                        }
                    }
                    events.Clear();
                }
                if (tempEvents != null)
                {
                    sink.Flush(tempEvents);
                }

                lock (profileLock)
                {
                    tempProfiles = new List <Profile>(profileData);
                }
                profileData.Clear();

                if (tempProfiles != null)
                {
                    sink.Flush(tempProfiles);
                }
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
            }

            try
            {
                sink.FlushComplete();
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
            }

            try
            {
                // this will have no effect if the clock is in the process of cancelling
                clock.ExecuteAfterDelay(flushInterval);
            }
            catch (Exception e)
            {
                Console.Error.Write(e.Message);
            }
        }