private[this] def midPoint()

in server/src/main/scala/com/twitter/server/handler/HistogramQueryHandler.scala [218:275]


  private[this] def midPoint(bc: BucketAndCount): Double =
    if (bc.upperLimit >= Int.MaxValue) bc.lowerLimit
    else (bc.upperLimit + bc.lowerLimit) / 2.0

  private[handler] def generateSummary(histoName: String): Option[Summary] = {
    histograms.get(histoName).map { detail =>
      val bcs = detail.counts.sortBy(_.lowerLimit)

      // first, the basic computations: sum, count, min, max, average
      val min = bcs.headOption.map(_.lowerLimit)
      val max = bcs.lastOption.map(_.upperLimit)
      var sum = 0.0
      var count = 0L
      bcs.foreach { bc =>
        count += bc.count
        sum += bc.count.toDouble * midPoint(bc)
      }
      val average =
        if (count == 0L) None
        else Some(sum.toLong / count)

      // note: this is modeled after `c.t.f.stats.BucketedHistogram.percentile`
      def percentile(total: Long, p: Double): Long = {
        if (p < 0.0 || p > 1.0)
          throw new AssertionError(s"percentile must be within 0.0 to 1.0 inclusive: $p")

        val target = Math.round(p * total)

        val iter = bcs.iterator
        var sum = 0L
        var bc: BucketAndCount = null
        while (iter.hasNext && sum < target) {
          bc = iter.next()
          sum += bc.count
        }
        bc match {
          case null => 0
          case _ if !iter.hasNext => max.getOrElse(0)
          case _ => midPoint(bc).toLong
        }
      }

      val percentiles: Map[String, Long] = SummaryThresholds.map {
        case (name, p) =>
          name -> percentile(count, p)
      }.toMap

      Summary(
        name = histoName,
        count = count,
        sum = sum.toLong,
        average = average,
        min = min,
        max = max,
        percentiles = percentiles
      )
    }
  }