public StatisticBucket Penalize(double penalty)
        {
            var total            = Interlocked.Read(ref totalCount);
            var successSum       = InterlockedEx.Read(ref successLatencySum);
            var successSquareSum = InterlockedEx.Read(ref successLatencySquaredSum);
            var rejected         = Interlocked.Read(ref rejectCount);
            var rejectSum        = InterlockedEx.Read(ref rejectLatencySum);
            var rejectSquareSum  = InterlockedEx.Read(ref rejectLatencySquaredSum);

            return(new StatisticBucket(
                       total,
                       rejected,
                       successSum,
                       successSquareSum,
                       PenalizeLatency(
                           rejectSum,
                           rejected,
                           penalty),
                       PenalizeSquaredLatency(
                           rejectSum,
                           rejectSquareSum,
                           rejected,
                           penalty)
                       ));
        }
        public AggregatedStatistic Aggregate(DateTime timestamp)
        {
            var total = Math.Max(1, Interlocked.Read(ref totalCount));
            var mean  = (InterlockedEx.Read(ref successLatencySum) + InterlockedEx.Read(ref rejectLatencySum)) / total;

            var squaredMean   = (InterlockedEx.Read(ref successLatencySquaredSum) + InterlockedEx.Read(ref rejectLatencySquaredSum)) / total;
            var variance      = Math.Max(0d, squaredMean - mean * mean);
            var stdDev        = Math.Sqrt(variance);
            var errorFraction = (double)Interlocked.Read(ref rejectCount) / total;

            return(new AggregatedStatistic(total, errorFraction, stdDev, mean, timestamp));
        }
 public void Report(ReplicaResult result)
 {
     Interlocked.Increment(ref totalCount);
     if (result.Verdict == ResponseVerdict.Accept)
     {
         InterlockedEx.Add(ref successLatencySum, result.Time.TotalMilliseconds);
         InterlockedEx.Add(ref successLatencySquaredSum, result.Time.TotalMilliseconds * result.Time.TotalMilliseconds);
     }
     else
     {
         Interlocked.Increment(ref rejectCount);
         InterlockedEx.Add(ref rejectLatencySum, result.Time.TotalMilliseconds);
         InterlockedEx.Add(ref rejectLatencySquaredSum, result.Time.TotalMilliseconds * result.Time.TotalMilliseconds);
     }
 }