aboutsummaryrefslogtreecommitdiff
path: root/kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala
diff options
context:
space:
mode:
Diffstat (limited to 'kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala')
-rw-r--r--kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala92
1 files changed, 92 insertions, 0 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