package kamon.newrelic
import kamon.metric.instrument._
import kamon.metric.MetricKey
import kamon.util.{ MapMerge, Timestamp }
case class MetricID(name: String, scope: Option[String])
case class MetricData(callCount: Long, total: Double, totalExclusive: Double, min: Double, max: Double, sumOfSquares: Double) {
def merge(that: MetricData): MetricData =
MetricData(
callCount + that.callCount,
total + that.total,
totalExclusive + that.totalExclusive,
math.min(min, that.min),
math.max(max, that.max),
sumOfSquares + that.sumOfSquares)
}
object Metric {
def scaleFunction(uom: UnitOfMeasurement): Long ⇒ Double = uom match {
case time: Time ⇒ time.scale(Time.Seconds)
case other ⇒ _.toDouble
}
def apply(snapshot: InstrumentSnapshot, snapshotUnit: UnitOfMeasurement, name: String, scope: Option[String]): Metric = {
snapshot match {
case hs: Histogram.Snapshot ⇒
var total: Double = 0D
var sumOfSquares: Double = 0D
val scaler = scaleFunction(snapshotUnit)
val scaledMin = scaler(hs.min)
val scaledMax = scaler(hs.max)
hs.recordsIterator.foreach { record ⇒
val scaledValue = scaler(record.level)
total += scaledValue * record.count
sumOfSquares += (scaledValue * scaledValue) * record.count
}
(MetricID(name, scope), MetricData(hs.numberOfMeasurements, total, total, scaledMin, scaledMax, sumOfSquares))
case cs: Counter.Snapshot ⇒
(MetricID(name, scope), MetricData(cs.count, cs.count, cs.count, 0, cs.count, cs.count * cs.count))
}
}
}
case class TimeSliceMetrics(from: Timestamp, to: Timestamp, metrics: Map[MetricID, MetricData]) {
import MapMerge.Syntax
def merge(that: TimeSliceMetrics): TimeSliceMetrics = {
val mergedFrom = Timestamp.earlier(from, that.from)
val mergedTo = Timestamp.later(to, that.to)
val mergedMetrics = metrics.merge(that.metrics, (l, r) ⇒ l.merge(r))
TimeSliceMetrics(mergedFrom, mergedTo, mergedMetrics)
}
}
case class MetricBatch(runID: Long, timeSliceMetrics: TimeSliceMetrics)