public void TracksStartAndEndTimesOfAggregation()
        {
            // create an aggregator
            var aggregator = new Int64CounterSumAggregator();

            aggregator.Update(1);
            Thread.Sleep(TimeSpan.FromMilliseconds(1));
            aggregator.Checkpoint();
            var metricData = aggregator.ToMetricData();

            aggregator.Update(2);
            Thread.Sleep(TimeSpan.FromMilliseconds(1));
            aggregator.Checkpoint();
            var otherMetricData = aggregator.ToMetricData();

            Assert.True(DateTime.Compare(metricData.StartTimestamp, metricData.Timestamp) < 0);
            Assert.True(DateTime.Compare(metricData.Timestamp, otherMetricData.StartTimestamp) < 0);
            Assert.True(
                DateTime.Compare(
                    metricData.Timestamp.Add(TimeSpan.FromTicks(1)),
                    otherMetricData.StartTimestamp) == 0);
            Assert.True(DateTime.Compare(otherMetricData.StartTimestamp, otherMetricData.Timestamp) < 0);
        }
        public void CounterAggregatorAggregatesCorrectlyWhenMultipleThreadsUpdatesLong()
        {
            // create an aggregator
            var aggregator = new Int64CounterSumAggregator();
            var sum        = aggregator.ToMetricData() as Int64SumData;

            // we start with 0.
            Assert.Equal(0, sum.Sum);

            // setup args to threads.
            var mre = new ManualResetEvent(false);
            var mreToEnsureAllThreadsStart = new ManualResetEvent(false);

            var argToThread =
                new UpdateThreadArguments <long>
            {
                CounterSumAggregator       = aggregator,
                ThreadsStartedCount        = 0,
                MreToBlockUpdateThread     = mre,
                MreToEnsureAllThreadsStart = mreToEnsureAllThreadsStart,
            };

            Thread[] t = new Thread[10];
            for (int i = 0; i < 10; i++)
            {
                t[i] = new Thread(LongMetricUpdateThread);
                t[i].Start(argToThread);
            }

            // Block until all 10 threads started.
            mreToEnsureAllThreadsStart.WaitOne();

            // kick-off all the threads.
            mre.Set();

            for (int i = 0; i < 10; i++)
            {
                // wait for all threads to complete
                t[i].Join();
            }

            // check point.
            aggregator.Checkpoint();
            sum = aggregator.ToMetricData() as Int64SumData;

            // 1000000 times 10 by each thread. times 10 as there are 10 threads
            Assert.Equal(100000000, sum.Sum);
        }