diff options
author | Ivan Topolnjak <ivantopo@gmail.com> | 2014-07-23 15:08:59 -0300 |
---|---|---|
committer | Ivan Topolnjak <ivantopo@gmail.com> | 2014-07-23 15:08:59 -0300 |
commit | 860c568db90699ea58ef13c5a5cdc08ccc3dbb07 (patch) | |
tree | bc7f07a6271c46ec84e784a6ee90302d3671e110 | |
parent | a0157772ad132ca449a9f5dfe6a2242af21b0c31 (diff) | |
download | Kamon-860c568db90699ea58ef13c5a5cdc08ccc3dbb07.tar.gz Kamon-860c568db90699ea58ef13c5a5cdc08ccc3dbb07.tar.bz2 Kamon-860c568db90699ea58ef13c5a5cdc08ccc3dbb07.zip |
+ core,spray: create and implement http server metrics for spray, related to #56
-rw-r--r-- | kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala | 92 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/metric/TraceMetrics.scala | 2 |
2 files changed, 93 insertions, 1 deletions
diff --git a/kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala b/kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala new file mode 100644 index 00000000..3773e7d8 --- /dev/null +++ b/kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala @@ -0,0 +1,92 @@ +package kamon.http + +import akka.actor.ActorSystem +import com.typesafe.config.Config +import kamon.metric.instrument.Counter +import kamon.metric._ + +import scala.collection.concurrent.TrieMap + +object HttpServerMetrics extends MetricGroupIdentity { + val name: String = "http-server-metrics-recorder" + val category = new MetricGroupCategory { + val name: String = "http-server" + } + + type TraceName = String + type StatusCode = String + + case class CountPerStatusCode(statusCode: String) extends MetricIdentity { + def name: String = statusCode + } + + case class TraceCountPerStatus(traceName: TraceName, statusCode: StatusCode) extends MetricIdentity { + def name: String = traceName + "_" + statusCode + } + + class HttpServerMetricsRecorder extends MetricGroupRecorder { + + private val counters = TrieMap[StatusCode, Counter]() + private val countersPerTrace = TrieMap[TraceName, TrieMap[StatusCode, Counter]]() + + def recordResponse(statusCode: StatusCode): Unit = recordResponse(statusCode, 1L) + + def recordResponse(statusCode: StatusCode, count: Long): Unit = + counters.getOrElseUpdate(statusCode, Counter()).increment(count) + + def recordResponse(traceName: TraceName, statusCode: StatusCode): Unit = recordResponse(traceName, statusCode, 1L) + + def recordResponse(traceName: TraceName, statusCode: StatusCode, count: Long): Unit = { + recordResponse(statusCode, count) + countersPerTrace.getOrElseUpdate(traceName, TrieMap()).getOrElseUpdate(statusCode, Counter()).increment(count) + } + + def collect(context: CollectionContext): HttpServerMetricsSnapshot = { + val countsPerStatusCode = counters.map { + case (statusCode, counter) ⇒ (statusCode, counter.collect(context)) + }.toMap + + val countsPerTraceAndStatus = countersPerTrace.map { + case (traceName, countsPerStatus) ⇒ + (traceName, countsPerStatus.map { case (statusCode, counter) ⇒ (statusCode, counter.collect(context)) }.toMap) + }.toMap + + HttpServerMetricsSnapshot(countsPerStatusCode, countsPerTraceAndStatus) + } + + def cleanup: Unit = {} + } + + case class HttpServerMetricsSnapshot(countsPerStatusCode: Map[StatusCode, Counter.Snapshot], + countsPerTraceAndStatusCode: Map[TraceName, Map[StatusCode, Counter.Snapshot]]) extends MetricGroupSnapshot { + + type GroupSnapshotType = HttpServerMetricsSnapshot + + def merge(that: HttpServerMetricsSnapshot, context: CollectionContext): HttpServerMetricsSnapshot = { + val combinedCountsPerStatus = combineMaps(countsPerStatusCode, that.countsPerStatusCode)((l, r) ⇒ l.merge(r, context)) + val combinedCountsPerTraceAndStatus = combineMaps(countsPerTraceAndStatusCode, that.countsPerTraceAndStatusCode) { + (leftCounts, rightCounts) ⇒ combineMaps(leftCounts, rightCounts)((l, r) ⇒ l.merge(r, context)) + } + HttpServerMetricsSnapshot(combinedCountsPerStatus, combinedCountsPerTraceAndStatus) + } + + def metrics: Map[MetricIdentity, MetricSnapshot] = { + countsPerStatusCode.map { + case (statusCode, count) ⇒ (CountPerStatusCode(statusCode), count) + } ++ { + for ( + (traceName, countsPerStatus) ← countsPerTraceAndStatusCode; + (statusCode, count) ← countsPerStatus + ) yield (TraceCountPerStatus(traceName, statusCode), count) + } + } + } + + val Factory = new MetricGroupFactory { + type GroupRecorder = HttpServerMetricsRecorder + + def create(config: Config, system: ActorSystem): HttpServerMetricsRecorder = + new HttpServerMetricsRecorder() + } + +}
\ No newline at end of file diff --git a/kamon-core/src/main/scala/kamon/metric/TraceMetrics.scala b/kamon-core/src/main/scala/kamon/metric/TraceMetrics.scala index 1ee1eab4..187eb07d 100644 --- a/kamon-core/src/main/scala/kamon/metric/TraceMetrics.scala +++ b/kamon-core/src/main/scala/kamon/metric/TraceMetrics.scala @@ -54,7 +54,7 @@ object TraceMetrics extends MetricGroupCategory { type GroupSnapshotType = TraceMetricsSnapshot def merge(that: TraceMetricsSnapshot, context: CollectionContext): TraceMetricsSnapshot = - TraceMetricsSnapshot(elapsedTime.merge(that.elapsedTime, context), Map.empty) + TraceMetricsSnapshot(elapsedTime.merge(that.elapsedTime, context), Map.empty) // TODO: Merge the segments metrics correctly and test it! def metrics: Map[MetricIdentity, MetricSnapshot] = segments + (ElapsedTime -> elapsedTime) } |