From 522a12c90788c402a364407e146d302e6519a3da Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Wed, 5 Feb 2014 01:12:34 -0300 Subject: kamon-newrelic now uses the subscription protocol to report metrics to NewRelic --- kamon-newrelic/src/main/resources/reference.conf | 6 +-- .../scala/kamon/newrelic/MetricTranslator.scala | 4 +- .../src/main/scala/kamon/newrelic/NewRelic.scala | 3 ++ .../kamon/newrelic/WebTransactionMetrics.scala | 43 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 9 deletions(-) (limited to 'kamon-newrelic') diff --git a/kamon-newrelic/src/main/resources/reference.conf b/kamon-newrelic/src/main/resources/reference.conf index dacabe41..ee0acdc3 100644 --- a/kamon-newrelic/src/main/resources/reference.conf +++ b/kamon-newrelic/src/main/resources/reference.conf @@ -1,9 +1,7 @@ -akka { - extensions = ["kamon.newrelic.NewRelic"] -} - kamon { newrelic { + apdexT = 1 second + app-name = "Kamon[Development]" license-key = 2e24765acb032cb9e7207013b5ba3e2ab7d2d75c } diff --git a/kamon-newrelic/src/main/scala/kamon/newrelic/MetricTranslator.scala b/kamon-newrelic/src/main/scala/kamon/newrelic/MetricTranslator.scala index 39177e30..c3438df5 100644 --- a/kamon-newrelic/src/main/scala/kamon/newrelic/MetricTranslator.scala +++ b/kamon-newrelic/src/main/scala/kamon/newrelic/MetricTranslator.scala @@ -24,9 +24,11 @@ class MetricTranslator(receiver: ActorRef) extends Actor with WebTransactionMetr def receive = { case TickMetricSnapshot(from, to, metrics) => + val scaledFrom = (from / 1E3).toInt + val scaledTo = (to / 1E3).toInt val allMetrics = collectWebTransactionMetrics(metrics) - receiver ! TimeSliceMetrics(from, to, allMetrics) + receiver ! TimeSliceMetrics(scaledFrom, scaledTo, allMetrics) } } diff --git a/kamon-newrelic/src/main/scala/kamon/newrelic/NewRelic.scala b/kamon-newrelic/src/main/scala/kamon/newrelic/NewRelic.scala index ef2de343..92191842 100644 --- a/kamon-newrelic/src/main/scala/kamon/newrelic/NewRelic.scala +++ b/kamon-newrelic/src/main/scala/kamon/newrelic/NewRelic.scala @@ -24,7 +24,10 @@ import akka.actor class NewRelicExtension(system: ExtendedActorSystem) extends Kamon.Extension { + val config = system.settings.config.getConfig("kamon.newrelic") + val manager: ActorRef = system.actorOf(Props[NewRelicManager], "kamon-newrelic") + val apdexT: Double = config.getMilliseconds("apdexT") / 1E3 // scale to seconds. Kamon(Metrics)(system).subscribe(TraceMetrics, "*", manager, permanently = true) } diff --git a/kamon-newrelic/src/main/scala/kamon/newrelic/WebTransactionMetrics.scala b/kamon-newrelic/src/main/scala/kamon/newrelic/WebTransactionMetrics.scala index 7fe5793c..31a3669d 100644 --- a/kamon-newrelic/src/main/scala/kamon/newrelic/WebTransactionMetrics.scala +++ b/kamon-newrelic/src/main/scala/kamon/newrelic/WebTransactionMetrics.scala @@ -16,18 +16,53 @@ package kamon.newrelic -import kamon.metrics.{ TraceMetrics, MetricGroupSnapshot, MetricGroupIdentity } +import kamon.metrics._ import kamon.metrics.TraceMetrics.ElapsedTime +import akka.actor.Actor +import kamon.Kamon trait WebTransactionMetrics { - def collectWebTransactionMetrics(metrics: Map[MetricGroupIdentity, MetricGroupSnapshot]): List[NewRelic.Metric] = { + self: Actor => + + def collectWebTransactionMetrics(metrics: Map[MetricGroupIdentity, MetricGroupSnapshot]): Seq[NewRelic.Metric] = { + val apdexBuilder = new ApdexBuilder("Apdex", None, (NewRelic)(context.system).apdexT) + var accumulatedHttpDispatcher: MetricSnapshot = DefaultMetricSnapshot.empty + val webTransactionMetrics = metrics.collect { case (TraceMetrics(name), groupSnapshot) ⇒ + groupSnapshot.metrics collect { - case (ElapsedTime, snapshot) => toNewRelicMetric("HttpDispatcher", None, snapshot) + case (ElapsedTime, snapshot) => + accumulatedHttpDispatcher = accumulatedHttpDispatcher.merge(snapshot) + snapshot.measurementLevels.foreach(level => apdexBuilder.record(level.value / 1E9D, level.count)) + + toNewRelicMetric(s"WebTransaction/Custom/$name", None, snapshot) } } - webTransactionMetrics.flatten.toList + val httpDispatcher = toNewRelicMetric("HttpDispatcher", None, accumulatedHttpDispatcher) + val webTransaction = toNewRelicMetric("WebTransaction", None, accumulatedHttpDispatcher) + + Seq(httpDispatcher, webTransaction, apdexBuilder.build) ++ webTransactionMetrics.flatten.toSeq } } + +class ApdexBuilder(name: String, scope: Option[String], apdexT: Double) { + val frustratingThreshold = 4 * apdexT + + var satisfying = 0L + var tolerating = 0L + var frustrating = 0L + + def record(duration: Double, count: Long): Unit = + if(duration <= apdexT) + satisfying += count + else + if(duration <= frustratingThreshold) + tolerating += count + else + frustrating += count + + // NewRelic reuses the same metric structure for recording the Apdex.. weird, but that's how it works. + def build: NewRelic.Metric = NewRelic.Metric(name, scope, satisfying, tolerating, frustrating, apdexT, apdexT, 0) +} -- cgit v1.2.3