aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego <diegolparra@gmail.com>2014-06-24 23:35:14 -0300
committerDiego <diegolparra@gmail.com>2014-07-21 17:13:28 -0300
commit5c141733ad39cf2730cf34dc8f3f4a82f0c1b516 (patch)
treeab2830795cacae80aa232e41ed224534572ba678
parenta96f6dadd5f77271672215e731b842ce785954f4 (diff)
downloadKamon-5c141733ad39cf2730cf34dc8f3f4a82f0c1b516.tar.gz
Kamon-5c141733ad39cf2730cf34dc8f3f4a82f0c1b516.tar.bz2
Kamon-5c141733ad39cf2730cf34dc8f3f4a82f0c1b516.zip
! kamon-system-metrics: introducing System and JVM metrics module
-rw-r--r--kamon-core/src/main/scala/kamon/metric/instrument/Gauge.scala8
-rw-r--r--kamon-playground/src/main/resources/application.conf1
-rw-r--r--kamon-system-metrics/src/main/resources/reference.conf76
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala84
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala75
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala82
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala96
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/NetworkMetrics.scala94
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala76
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala64
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/SigarLoader.scala131
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/index (renamed from kamon-system/src/main/scala/kamon/system/native/index)0
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-freebsd-6.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-freebsd-6.so)bin210641 -> 210641 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-linux.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-linux.so)bin246605 -> 246605 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-solaris.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-solaris.so)bin251360 -> 251360 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ia64-hpux-11.sl (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-ia64-hpux-11.sl)bin577452 -> 577452 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ia64-linux.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-ia64-linux.so)bin494929 -> 494929 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-pa-hpux-11.sl (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-pa-hpux-11.sl)bin516096 -> 516096 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc-aix-5.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-ppc-aix-5.so)bin400925 -> 400925 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc-linux.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-ppc-linux.so)bin258547 -> 258547 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc64-aix-5.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-ppc64-aix-5.so)bin425077 -> 425077 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc64-linux.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-ppc64-linux.so)bin330767 -> 330767 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-s390x-linux.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-s390x-linux.so)bin269932 -> 269932 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-sparc-solaris.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-sparc-solaris.so)bin285004 -> 285004 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-sparc64-solaris.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-sparc64-solaris.so)bin261896 -> 261896 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-universal-macosx.dylib (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-universal-macosx.dylib)bin377668 -> 377668 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-universal64-macosx.dylib (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-universal64-macosx.dylib)bin397440 -> 397440 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-freebsd-5.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-x86-freebsd-5.so)bin179751 -> 179751 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-freebsd-6.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-x86-freebsd-6.so)bin179379 -> 179379 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-linux.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-x86-linux.so)bin233385 -> 233385 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-solaris.so (renamed from kamon-system/src/main/scala/kamon/system/native/libsigar-x86-solaris.so)bin242880 -> 242880 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/sigar-amd64-winnt.dll (renamed from kamon-system/src/main/scala/kamon/system/native/sigar-amd64-winnt.dll)bin402432 -> 402432 bytes
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/native/sigar-x86-winnt.dll (renamed from kamon-system/src/main/scala/kamon/system/native/sigar-x86-winnt.dll)bin266240 -> 266240 bytes
-rw-r--r--kamon-system-metrics/src/test/scala/kamon/metrics/SystemMetricsSpec.scala331
-rw-r--r--kamon-system/src/main/resources/reference.conf28
-rw-r--r--kamon-system/src/main/scala/kamon/metrics/CpuMetricsCollector.scala74
-rw-r--r--kamon-system/src/main/scala/kamon/metrics/JvmMetrics.scala71
-rw-r--r--kamon-system/src/main/scala/kamon/metrics/SystemMetrics.scala71
-rw-r--r--kamon-system/src/main/scala/kamon/system/System.scala36
-rw-r--r--kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala82
-rw-r--r--project/Dependencies.scala2
-rw-r--r--project/Projects.scala14
42 files changed, 1127 insertions, 369 deletions
diff --git a/kamon-core/src/main/scala/kamon/metric/instrument/Gauge.scala b/kamon-core/src/main/scala/kamon/metric/instrument/Gauge.scala
index 1efff2bc..efd7d78f 100644
--- a/kamon-core/src/main/scala/kamon/metric/instrument/Gauge.scala
+++ b/kamon-core/src/main/scala/kamon/metric/instrument/Gauge.scala
@@ -44,14 +44,18 @@ object Gauge {
fromConfig(config, system)(currentValueCollector)
}
- def fromConfig(config: Config, system: ActorSystem)(currentValueCollector: CurrentValueCollector): Gauge = {
+ def fromConfig(config: Config, system: ActorSystem, scale: Scale)(currentValueCollector: CurrentValueCollector): Gauge = {
import scala.concurrent.duration._
val highest = config.getLong("highest-trackable-value")
val significantDigits = config.getInt("significant-value-digits")
val refreshInterval = config.getDuration("refresh-interval", TimeUnit.MILLISECONDS)
- Gauge(Histogram.Precision(significantDigits), highest, Scale.Unit, refreshInterval.millis, system)(currentValueCollector)
+ Gauge(Histogram.Precision(significantDigits), highest, scale, refreshInterval.millis, system)(currentValueCollector)
+ }
+
+ def fromConfig(config: Config, system: ActorSystem)(currentValueCollector: CurrentValueCollector): Gauge = {
+ fromConfig(config, system, Scale.Unit)(currentValueCollector)
}
implicit def functionZeroAsCurrentValueCollector(f: () ⇒ Long): CurrentValueCollector = new CurrentValueCollector {
diff --git a/kamon-playground/src/main/resources/application.conf b/kamon-playground/src/main/resources/application.conf
index 3d57141a..af85207f 100644
--- a/kamon-playground/src/main/resources/application.conf
+++ b/kamon-playground/src/main/resources/application.conf
@@ -1,6 +1,7 @@
akka {
loglevel = INFO
+ extensions = ["kamon.system.SystemMetrics"]
actor {
debug {
diff --git a/kamon-system-metrics/src/main/resources/reference.conf b/kamon-system-metrics/src/main/resources/reference.conf
new file mode 100644
index 00000000..d6eb0576
--- /dev/null
+++ b/kamon-system-metrics/src/main/resources/reference.conf
@@ -0,0 +1,76 @@
+# ============================================ #
+# Kamon-System-Metrics Reference Configuration #
+# ============================================ #
+
+kamon {
+ metrics {
+ precision {
+ system {
+ process-cpu {
+ user = {
+ refresh-interval = 100 milliseconds
+ highest-trackable-value = 999999999
+ significant-value-digits = 2
+ }
+ system = {
+ refresh-interval = 100 milliseconds
+ highest-trackable-value = 999999999
+ significant-value-digits = 2
+ }
+ }
+
+ cpu {
+ user = {
+ refresh-interval = 100 milliseconds
+ highest-trackable-value = 999999999
+ significant-value-digits = 2
+ }
+ system = {
+ refresh-interval = 100 milliseconds
+ highest-trackable-value = 999999999
+ significant-value-digits = 2
+ }
+ wait = {
+ refresh-interval = 100 milliseconds
+ highest-trackable-value = 999999999
+ significant-value-digits = 2
+ }
+ idle ={
+ refresh-interval = 100 milliseconds
+ highest-trackable-value = 999999999
+ significant-value-digits = 2
+ }
+ }
+
+ network {
+ rx-bytes = ${kamon.metrics.precision.default-gauge-precision}
+ tx-bytes = ${kamon.metrics.precision.default-gauge-precision}
+ rx-errors = ${kamon.metrics.precision.default-gauge-precision}
+ tx-errors = ${kamon.metrics.precision.default-gauge-precision}
+ }
+
+ memory {
+ used = ${kamon.metrics.precision.default-gauge-precision}
+ free = ${kamon.metrics.precision.default-gauge-precision}
+ buffer = ${kamon.metrics.precision.default-gauge-precision}
+ cache = ${kamon.metrics.precision.default-gauge-precision}
+ swap-used = ${kamon.metrics.precision.default-gauge-precision}
+ swap-free = ${kamon.metrics.precision.default-gauge-precision}
+ }
+ }
+
+ jvm {
+ heap {
+ used = ${kamon.metrics.precision.default-gauge-precision}
+ max = ${kamon.metrics.precision.default-gauge-precision}
+ committed = ${kamon.metrics.precision.default-gauge-precision}
+ }
+
+ gc {
+ count = ${kamon.metrics.precision.default-gauge-precision}
+ time = ${kamon.metrics.precision.default-gauge-precision}
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala
new file mode 100644
index 00000000..c098d1e5
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala
@@ -0,0 +1,84 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.metrics
+
+import akka.actor.ActorSystem
+import com.typesafe.config.Config
+import kamon.metric.instrument.{ Gauge, Histogram }
+import kamon.metric._
+import kamon.system.SigarExtensionProvider
+import org.hyperic.sigar.SigarProxy
+
+case class CPUMetrics(name: String) extends MetricGroupIdentity {
+ val category = CPUMetrics
+}
+
+object CPUMetrics extends MetricGroupCategory {
+ val name = "cpu"
+
+ case object User extends MetricIdentity { val name = "user" }
+ case object System extends MetricIdentity { val name = "system" }
+ case object Wait extends MetricIdentity { val name = "wait" }
+ case object Idle extends MetricIdentity { val name = "idle" }
+
+ case class CPUMetricRecorder(user: Gauge, system: Gauge, cpuWait: Gauge, idle: Gauge)
+ extends MetricGroupRecorder {
+
+ def collect(context: CollectionContext): MetricGroupSnapshot = {
+ CPUMetricSnapshot(user.collect(context), system.collect(context), cpuWait.collect(context), idle.collect(context))
+ }
+
+ def cleanup: Unit = {}
+ }
+
+ case class CPUMetricSnapshot(user: Histogram.Snapshot, system: Histogram.Snapshot, cpuWait: Histogram.Snapshot, idle: Histogram.Snapshot)
+ extends MetricGroupSnapshot {
+
+ type GroupSnapshotType = CPUMetricSnapshot
+
+ def merge(that: CPUMetricSnapshot, context: CollectionContext): GroupSnapshotType = {
+ CPUMetricSnapshot(user.merge(that.user, context), system.merge(that.system, context), cpuWait.merge(that.cpuWait, context), idle.merge(that.idle, context))
+ }
+
+ lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
+ User -> user,
+ System -> system,
+ Wait -> cpuWait,
+ Idle -> idle)
+ }
+
+ val Factory = new MetricGroupFactory with SigarExtensionProvider {
+ def cpu = sigar.getCpu
+
+ type GroupRecorder = CPUMetricRecorder
+
+ def create(config: Config, system: ActorSystem): GroupRecorder = {
+ val settings = config.getConfig("precision.system.cpu")
+
+ val userConfig = settings.getConfig("user")
+ val systemConfig = settings.getConfig("system")
+ val cpuWaitConfig = settings.getConfig("wait")
+ val idleConfig = settings.getConfig("idle")
+
+ new CPUMetricRecorder(
+ Gauge.fromConfig(userConfig, system)(() ⇒ cpu.getUser),
+ Gauge.fromConfig(systemConfig, system)(() ⇒ cpu.getSys),
+ Gauge.fromConfig(cpuWaitConfig, system)(() ⇒ cpu.getWait),
+ Gauge.fromConfig(idleConfig, system)(() ⇒ cpu.getIdle))
+ }
+ }
+}
+
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala
new file mode 100644
index 00000000..b5da600e
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala
@@ -0,0 +1,75 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.metrics
+
+import java.lang.management.GarbageCollectorMXBean
+
+import akka.actor.ActorSystem
+import com.typesafe.config.Config
+import kamon.metric._
+import kamon.metric.instrument.{ Gauge, Histogram }
+
+case class GCMetrics(name: String) extends MetricGroupIdentity {
+ val category = GCMetrics
+}
+
+object GCMetrics extends MetricGroupCategory {
+ val name = "gc"
+
+ case object CollectionCount extends MetricIdentity { val name = "collection-count" }
+ case object CollectionTime extends MetricIdentity { val name = "collection-time" }
+
+ case class GCMetricRecorder(count: Gauge, time: Gauge)
+ extends MetricGroupRecorder {
+
+ def collect(context: CollectionContext): MetricGroupSnapshot = {
+ GCMetricSnapshot(count.collect(context), time.collect(context))
+ }
+
+ def cleanup: Unit = {}
+ }
+
+ case class GCMetricSnapshot(count: Histogram.Snapshot, time: Histogram.Snapshot)
+ extends MetricGroupSnapshot {
+
+ type GroupSnapshotType = GCMetricSnapshot
+
+ def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
+ GCMetricSnapshot(count.merge(that.count, context), time.merge(that.time, context))
+ }
+
+ lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
+ CollectionCount -> count,
+ CollectionTime -> time)
+ }
+
+ def Factory(gc: GarbageCollectorMXBean) = new MetricGroupFactory {
+
+ type GroupRecorder = GCMetricRecorder
+
+ def create(config: Config, system: ActorSystem): GroupRecorder = {
+ val settings = config.getConfig("precision.jvm.gc")
+
+ val countConfig = settings.getConfig("count")
+ val timeConfig = settings.getConfig("time")
+
+ new GCMetricRecorder(
+ Gauge.fromConfig(countConfig, system)(() ⇒ gc.getCollectionCount),
+ Gauge.fromConfig(timeConfig, system, Scale.Milli)(() ⇒ gc.getCollectionTime))
+ }
+ }
+}
+
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala
new file mode 100644
index 00000000..09174f47
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala
@@ -0,0 +1,82 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.metrics
+
+import java.lang.management.ManagementFactory
+
+import akka.actor.ActorSystem
+import com.typesafe.config.Config
+import kamon.metric._
+import kamon.metric.instrument.{ Gauge, Histogram }
+
+case class HeapMetrics(name: String) extends MetricGroupIdentity {
+ val category = HeapMetrics
+}
+
+object HeapMetrics extends MetricGroupCategory {
+ val name = "heap"
+
+ case object Used extends MetricIdentity { val name = "used-heap" }
+ case object Max extends MetricIdentity { val name = "max-heap" }
+ case object Committed extends MetricIdentity { val name = "committed-heap" }
+
+ case class HeapMetricRecorder(used: Gauge, max: Gauge, committed: Gauge)
+ extends MetricGroupRecorder {
+
+ def collect(context: CollectionContext): MetricGroupSnapshot = {
+ HeapMetricSnapshot(used.collect(context), max.collect(context), committed.collect(context))
+ }
+
+ def cleanup: Unit = {}
+ }
+
+ case class HeapMetricSnapshot(used: Histogram.Snapshot, max: Histogram.Snapshot, committed: Histogram.Snapshot)
+ extends MetricGroupSnapshot {
+
+ type GroupSnapshotType = HeapMetricSnapshot
+
+ def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
+ HeapMetricSnapshot(used.merge(that.used, context), max.merge(that.max, context), committed.merge(that.committed, context))
+ }
+
+ lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
+ Used -> used,
+ Max -> max,
+ Committed -> committed)
+ }
+
+ val Factory = new MetricGroupFactory {
+
+ val memory = ManagementFactory.getMemoryMXBean
+ def heap = memory.getHeapMemoryUsage
+
+ type GroupRecorder = HeapMetricRecorder
+
+ def create(config: Config, system: ActorSystem): GroupRecorder = {
+ val settings = config.getConfig("precision.jvm.heap")
+
+ val usedHeapConfig = settings.getConfig("used")
+ val maxHeapConfig = settings.getConfig("max")
+ val committedHeapConfig = settings.getConfig("committed")
+
+ new HeapMetricRecorder(
+ Gauge.fromConfig(usedHeapConfig, system)(() ⇒ heap.getUsed),
+ Gauge.fromConfig(maxHeapConfig, system)(() ⇒ heap.getMax),
+ Gauge.fromConfig(committedHeapConfig, system)(() ⇒ heap.getCommitted))
+ }
+ }
+}
+
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala
new file mode 100644
index 00000000..4f6cb1cd
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala
@@ -0,0 +1,96 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.metrics
+
+import akka.actor.ActorSystem
+import com.typesafe.config.Config
+import kamon.metric._
+import kamon.metric.instrument.Gauge.CurrentValueCollector
+import kamon.metric.instrument.{ Gauge, Histogram }
+import kamon.system.SigarExtensionProvider
+import org.hyperic.sigar.Mem
+
+case class MemoryMetrics(name: String) extends MetricGroupIdentity {
+ val category = MemoryMetrics
+}
+
+object MemoryMetrics extends MetricGroupCategory {
+ val name = "memory"
+
+ case object Used extends MetricIdentity { val name = "used" }
+ case object Free extends MetricIdentity { val name = "free" }
+ case object Buffer extends MetricIdentity { val name = "buffer" }
+ case object Cache extends MetricIdentity { val name = "cache" }
+ case object SwapUsed extends MetricIdentity { val name = "swap-used" }
+ case object SwapFree extends MetricIdentity { val name = "swap-free" }
+
+ case class MemoryMetricRecorder(used: Gauge, free: Gauge, buffer: Gauge, cache: Gauge, swapUsed: Gauge, swapFree: Gauge)
+ extends MetricGroupRecorder {
+
+ def collect(context: CollectionContext): MetricGroupSnapshot = {
+ MemoryMetricSnapshot(used.collect(context), free.collect(context), buffer.collect(context), cache.collect(context), swapUsed.collect(context), swapFree.collect(context))
+ }
+
+ def cleanup: Unit = {}
+ }
+
+ case class MemoryMetricSnapshot(used: Histogram.Snapshot, free: Histogram.Snapshot, buffer: Histogram.Snapshot, cache: Histogram.Snapshot, swapUsed: Histogram.Snapshot, swapFree: Histogram.Snapshot)
+ extends MetricGroupSnapshot {
+
+ type GroupSnapshotType = MemoryMetricSnapshot
+
+ def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
+ MemoryMetricSnapshot(used.merge(that.used, context), free.merge(that.free, context), buffer.merge(that.buffer, context), cache.merge(that.cache, context), swapUsed.merge(that.swapUsed, context), swapFree.merge(that.swapFree, context))
+ }
+
+ lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
+ Used -> used,
+ Free -> free,
+ Buffer -> buffer,
+ Cache -> cache,
+ SwapUsed -> swapUsed,
+ SwapFree -> swapFree)
+ }
+
+ val Factory = new MetricGroupFactory with SigarExtensionProvider {
+ def mem = sigar.getMem
+ def swap = sigar.getSwap
+
+ type GroupRecorder = MemoryMetricRecorder
+
+ def create(config: Config, system: ActorSystem): GroupRecorder = {
+ val settings = config.getConfig("precision.system.memory")
+
+ val usedConfig = settings.getConfig("used")
+ val freeConfig = settings.getConfig("free")
+ val bufferConfig = settings.getConfig("buffer")
+ val cacheConfig = settings.getConfig("cache")
+ val swapUsedConfig = settings.getConfig("swap-used")
+ val swapFreeConfig = settings.getConfig("swap-free")
+
+ new MemoryMetricRecorder(
+ Gauge.fromConfig(usedConfig, system)(() ⇒ mem.getUsed),
+ Gauge.fromConfig(freeConfig, system)(() ⇒ mem.getFree),
+ Gauge.fromConfig(bufferConfig, system)(() ⇒ swap.getUsed),
+ Gauge.fromConfig(cacheConfig, system)(() ⇒ swap.getFree),
+ Gauge.fromConfig(swapUsedConfig, system)(collectBuffer(mem)),
+ Gauge.fromConfig(swapFreeConfig, system)(collectCache(mem)))
+ }
+
+ private def collectBuffer(mem: Mem) = () ⇒ if (mem.getUsed() != mem.getActualUsed()) mem.getActualUsed() else 0L
+ private def collectCache(mem: Mem) = () ⇒ if (mem.getFree() != mem.getActualFree()) mem.getActualFree() else 0L
+ }
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/NetworkMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/NetworkMetrics.scala
new file mode 100644
index 00000000..62fc3fcd
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/metrics/NetworkMetrics.scala
@@ -0,0 +1,94 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.metrics
+
+import akka.actor.ActorSystem
+import com.typesafe.config.Config
+import kamon.metric._
+import kamon.metric.instrument.Gauge.CurrentValueCollector
+import kamon.metric.instrument.{ Gauge, Histogram }
+import kamon.system.SigarExtensionProvider
+import org.hyperic.sigar.{ NetInterfaceStat, SigarProxy }
+
+case class NetworkMetrics(name: String) extends MetricGroupIdentity {
+ val category = NetworkMetrics
+}
+
+object NetworkMetrics extends MetricGroupCategory {
+ val name = "network"
+
+ case object RxBytes extends MetricIdentity { val name = "rx-bytes" }
+ case object TxBytes extends MetricIdentity { val name = "tx-bytes" }
+ case object RxErrors extends MetricIdentity { val name = "rx-errors" }
+ case object TxErrors extends MetricIdentity { val name = "tx-errors" }
+
+ case class NetworkMetricRecorder(rxBytes: Gauge, txBytes: Gauge, rxErrors: Gauge, txErrors: Gauge)
+ extends MetricGroupRecorder {
+
+ def collect(context: CollectionContext): MetricGroupSnapshot = {
+ NetworkMetricSnapshot(rxBytes.collect(context), txBytes.collect(context), rxErrors.collect(context), txErrors.collect(context))
+ }
+
+ def cleanup: Unit = {}
+ }
+
+ case class NetworkMetricSnapshot(rxBytes: Histogram.Snapshot, txBytes: Histogram.Snapshot, rxErrors: Histogram.Snapshot, txErrors: Histogram.Snapshot)
+ extends MetricGroupSnapshot {
+
+ type GroupSnapshotType = NetworkMetricSnapshot
+
+ def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
+ NetworkMetricSnapshot(rxBytes.merge(that.rxBytes, context), txBytes.merge(that.txBytes, context), rxErrors.merge(that.rxErrors, context), txErrors.merge(that.txErrors, context))
+ }
+
+ val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
+ RxBytes -> rxBytes,
+ TxBytes -> txBytes,
+ RxErrors -> rxErrors,
+ TxErrors -> txErrors)
+ }
+
+ val Factory = new MetricGroupFactory with SigarExtensionProvider {
+
+ val interfaces: Set[String] = sigar.getNetInterfaceList.toSet
+
+ type GroupRecorder = NetworkMetricRecorder
+
+ def create(config: Config, system: ActorSystem): GroupRecorder = {
+ val settings = config.getConfig("precision.system.network")
+
+ val rxBytesConfig = settings.getConfig("rx-bytes")
+ val txBytesConfig = settings.getConfig("tx-bytes")
+ val rxErrorsConfig = settings.getConfig("rx-errors")
+ val txErrorsConfig = settings.getConfig("tx-errors")
+
+ new NetworkMetricRecorder(
+ Gauge.fromConfig(rxBytesConfig, system)(collect(sigar, interfaces)(net ⇒ net.getRxBytes)),
+ Gauge.fromConfig(txBytesConfig, system)(collect(sigar, interfaces)(net ⇒ net.getTxBytes)),
+ Gauge.fromConfig(rxErrorsConfig, system)(collect(sigar, interfaces)(net ⇒ net.getRxErrors)),
+ Gauge.fromConfig(txErrorsConfig, system)(collect(sigar, interfaces)(net ⇒ net.getTxErrors)))
+ }
+
+ private def collect(sigar: SigarProxy, interfaces: Set[String])(block: NetInterfaceStat ⇒ Long) = () ⇒ {
+ interfaces.foldLeft(0L) { (totalBytes, interface) ⇒
+ {
+ val net = sigar.getNetInterfaceStat(interface)
+ totalBytes + block(net)
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala
new file mode 100644
index 00000000..356504b7
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala
@@ -0,0 +1,76 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.metrics
+
+import akka.actor.ActorSystem
+import com.typesafe.config.Config
+import kamon.metric.instrument.{ Gauge, Histogram }
+import kamon.metric._
+import kamon.system.SigarExtensionProvider
+
+case class ProcessCPUMetrics(name: String) extends MetricGroupIdentity {
+ val category = ProcessCPUMetrics
+}
+
+object ProcessCPUMetrics extends MetricGroupCategory {
+ val name = "proc-cpu"
+
+ case object User extends MetricIdentity { val name = "user" }
+ case object System extends MetricIdentity { val name = "system" }
+
+ case class ProcessCPUMetricsRecorder(user: Gauge, system: Gauge)
+ extends MetricGroupRecorder {
+
+ def collect(context: CollectionContext): MetricGroupSnapshot = {
+ ProcessCPUMetricsSnapshot(user.collect(context), system.collect(context))
+ }
+
+ def cleanup: Unit = {}
+ }
+
+ case class ProcessCPUMetricsSnapshot(user: Histogram.Snapshot, system: Histogram.Snapshot)
+ extends MetricGroupSnapshot {
+
+ type GroupSnapshotType = ProcessCPUMetricsSnapshot
+
+ def merge(that: ProcessCPUMetricsSnapshot, context: CollectionContext): GroupSnapshotType = {
+ ProcessCPUMetricsSnapshot(user.merge(that.user, context), system.merge(that.system, context))
+ }
+
+ lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
+ User -> user,
+ System -> system)
+ }
+
+ val Factory = new MetricGroupFactory with SigarExtensionProvider {
+ def pid = sigar.getPid
+ def cpu = sigar.getProcCpu(pid)
+
+ type GroupRecorder = ProcessCPUMetricsRecorder
+
+ def create(config: Config, system: ActorSystem): GroupRecorder = {
+ val settings = config.getConfig("precision.system.process-cpu")
+
+ val userConfig = settings.getConfig("user")
+ val systemConfig = settings.getConfig("system")
+
+ new ProcessCPUMetricsRecorder(
+ Gauge.fromConfig(userConfig, system)(() ⇒ cpu.getUser),
+ Gauge.fromConfig(systemConfig, system)(() ⇒ cpu.getSys))
+ }
+ }
+}
+
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala
new file mode 100644
index 00000000..e46fca24
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala
@@ -0,0 +1,64 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+package kamon.system
+
+import java.lang.management.ManagementFactory
+
+import akka.actor._
+import akka.event.Logging
+import kamon.Kamon
+import kamon.metric.Metrics
+import kamon.metrics._
+import kamon.system.native.SigarLoader
+import scala.collection.JavaConverters._
+
+object SystemMetrics extends ExtensionId[SystemMetricsExtension] with ExtensionIdProvider {
+ override def lookup(): ExtensionId[_ <: Extension] = SystemMetrics
+
+ override def createExtension(system: ExtendedActorSystem): SystemMetricsExtension = new SystemMetricsExtension(system)
+}
+
+class SystemMetricsExtension(private val system: ExtendedActorSystem) extends Kamon.Extension {
+ import kamon.system.SystemMetricsExtension._
+
+ val log = Logging(system, classOf[SystemMetricsExtension])
+
+ log.info(s"Starting the Kamon(SystemMetrics) extension")
+
+ val systemMetricsExtension = Kamon(Metrics)(system)
+
+ systemMetricsExtension.register(CPUMetrics(CPU), CPUMetrics.Factory)
+ systemMetricsExtension.register(ProcessCPUMetrics(ProcessCPU), ProcessCPUMetrics.Factory)
+ systemMetricsExtension.register(NetworkMetrics(Network), NetworkMetrics.Factory)
+ systemMetricsExtension.register(MemoryMetrics(Memory), MemoryMetrics.Factory)
+ systemMetricsExtension.register(HeapMetrics(Heap), HeapMetrics.Factory)
+
+ garbageCollectors.map { gc ⇒ systemMetricsExtension.register(GCMetrics(gc.getName), GCMetrics.Factory(gc)) }
+}
+
+object SystemMetricsExtension {
+ val CPU = "cpu"
+ val ProcessCPU = "process-cpu"
+ val Network = "network"
+ val Memory = "memory"
+ val Heap = "heap"
+
+ val garbageCollectors = ManagementFactory.getGarbageCollectorMXBeans.asScala.filter(_.isValid)
+}
+
+trait SigarExtensionProvider {
+ lazy val sigar = SigarLoader.sigarProxy
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/native/SigarLoader.scala b/kamon-system-metrics/src/main/scala/kamon/system/native/SigarLoader.scala
new file mode 100644
index 00000000..6af0a6d2
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/SigarLoader.scala
@@ -0,0 +1,131 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+
+package kamon.system.native
+
+import java.io._
+import java.util
+import java.util.logging.Logger
+import java.util.{ ArrayList, List }
+
+import org.hyperic.sigar.{ SigarProxy, SigarProxyCache }
+
+import scala.annotation.tailrec
+import scala.collection.JavaConversions._
+import scala.io.Source
+
+object SigarLoader {
+
+ val Version = "1.6.4"
+ val JavaLibraryPath = "java.library.path"
+ val TmpDir = "java.io.tmpdir"
+ val IndexFile = "/kamon/system/native/index"
+ val UsrPathField = "usr_paths"
+
+ private val log = Logger.getLogger("SigarLoader")
+
+ def sigarProxy = init(new File(System.getProperty(TmpDir)))
+
+ private[native] def init(baseTmp: File): SigarProxy = {
+ val tmpDir = createTmpDir(baseTmp)
+ for (lib ← loadIndex) copy(lib, tmpDir)
+
+ attachToLibraryPath(tmpDir)
+
+ try {
+ val sigar = SigarProxyCache.newInstance()
+ sigar.getPid
+ sigar
+ } catch {
+ case t: Throwable ⇒ {
+ log.severe("Failed to load sigar")
+ throw new RuntimeException(t)
+ }
+ }
+ }
+
+ private[native] val usrPathField = {
+ val usrPathField = classOf[ClassLoader].getDeclaredField(UsrPathField)
+ usrPathField.setAccessible(true)
+ usrPathField
+ }
+
+ private[native] def attachToLibraryPath(dir: File): Unit = {
+ val dirAbsolute = dir.getAbsolutePath
+ System.setProperty(JavaLibraryPath, newLibraryPath(dirAbsolute))
+ var paths = usrPathField.get(null).asInstanceOf[Array[String]]
+ if (paths == null) paths = new Array[String](0)
+ for (path ← paths) if (path == dirAbsolute) return
+ val newPaths = util.Arrays.copyOf(paths, paths.length + 1)
+ newPaths(newPaths.length - 1) = dirAbsolute
+ usrPathField.set(null, newPaths)
+ }
+
+ private[native] def newLibraryPath(dirAbsolutePath: String): String = {
+ Option(System.getProperty(JavaLibraryPath)).fold(dirAbsolutePath)(oldValue ⇒ s"$dirAbsolutePath${File.pathSeparator}$oldValue")
+ }
+
+ private[native] def copy(lib: String, tmpDir: File) {
+ val target = new File(tmpDir, lib)
+ if (target.exists()) return
+ write(classOf[Loader].getResourceAsStream(lib), target)
+ }
+
+ private[native] def createTmpDir(baseTmp: File): File = {
+ val tmpDir = new File(baseTmp, s"sigar-$Version")
+ if (!tmpDir.exists()) {
+ if (!tmpDir.mkdirs()) throw new RuntimeException(s"Could not create temp sigar directory: ${tmpDir.getAbsolutePath}")
+ }
+ if (!tmpDir.isDirectory) throw new RuntimeException(s"sigar temp directory path is not a directory: ${tmpDir.getAbsolutePath}")
+ if (!tmpDir.canWrite()) throw new RuntimeException(s"sigar temp directory not writeable: ${tmpDir.getAbsolutePath}")
+ tmpDir
+ }
+
+ private[native] def loadIndex(): List[String] = {
+ val libs = new ArrayList[String]()
+ val is = classOf[Loader].getResourceAsStream(IndexFile)
+
+ for (line ← Source.fromInputStream(is).getLines()) {
+ val currentLine = line.trim()
+ libs add currentLine
+ }
+ libs
+ }
+
+ private[native] def write(input: InputStream, to: File) {
+ val out = new FileOutputStream(to)
+ try {
+ transfer(input, out)
+ } finally {
+ out.close()
+ }
+ }
+
+ private[native] def transfer(input: InputStream, out: OutputStream) {
+ val buffer = new Array[Byte](8192)
+
+ @tailrec def transfer() {
+ val read = input.read(buffer)
+ if (read >= 0) {
+ out.write(buffer, 0, read)
+ transfer()
+ }
+ }
+ transfer()
+ }
+
+ class Loader private[native]
+}
diff --git a/kamon-system/src/main/scala/kamon/system/native/index b/kamon-system-metrics/src/main/scala/kamon/system/native/index
index ebc7f952..ebc7f952 100644
--- a/kamon-system/src/main/scala/kamon/system/native/index
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/index
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-freebsd-6.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-freebsd-6.so
index 3e94f0d2..3e94f0d2 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-freebsd-6.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-freebsd-6.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-linux.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-linux.so
index 5a2e4c24..5a2e4c24 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-linux.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-linux.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-solaris.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-solaris.so
index 6396482a..6396482a 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-amd64-solaris.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-amd64-solaris.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-ia64-hpux-11.sl b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ia64-hpux-11.sl
index d92ea4a9..d92ea4a9 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-ia64-hpux-11.sl
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ia64-hpux-11.sl
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-ia64-linux.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ia64-linux.so
index 2bd2fc8e..2bd2fc8e 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-ia64-linux.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ia64-linux.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-pa-hpux-11.sl b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-pa-hpux-11.sl
index 0dfd8a11..0dfd8a11 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-pa-hpux-11.sl
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-pa-hpux-11.sl
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc-aix-5.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc-aix-5.so
index 7d4b5199..7d4b5199 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc-aix-5.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc-aix-5.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc-linux.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc-linux.so
index 4394b1b0..4394b1b0 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc-linux.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc-linux.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc64-aix-5.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc64-aix-5.so
index 35fd8288..35fd8288 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc64-aix-5.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc64-aix-5.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc64-linux.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc64-linux.so
index a1ba2529..a1ba2529 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-ppc64-linux.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-ppc64-linux.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-s390x-linux.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-s390x-linux.so
index c275f4ac..c275f4ac 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-s390x-linux.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-s390x-linux.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-sparc-solaris.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-sparc-solaris.so
index aa847d2b..aa847d2b 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-sparc-solaris.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-sparc-solaris.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-sparc64-solaris.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-sparc64-solaris.so
index 6c4fe809..6c4fe809 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-sparc64-solaris.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-sparc64-solaris.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-universal-macosx.dylib b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-universal-macosx.dylib
index 27ab1071..27ab1071 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-universal-macosx.dylib
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-universal-macosx.dylib
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-universal64-macosx.dylib b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-universal64-macosx.dylib
index 0c721fec..0c721fec 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-universal64-macosx.dylib
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-universal64-macosx.dylib
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-freebsd-5.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-freebsd-5.so
index 8c50c611..8c50c611 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-freebsd-5.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-freebsd-5.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-freebsd-6.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-freebsd-6.so
index f0800274..f0800274 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-freebsd-6.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-freebsd-6.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-linux.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-linux.so
index a0b64edd..a0b64edd 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-linux.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-linux.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-solaris.so b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-solaris.so
index c6452e56..c6452e56 100644
--- a/kamon-system/src/main/scala/kamon/system/native/libsigar-x86-solaris.so
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/libsigar-x86-solaris.so
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/sigar-amd64-winnt.dll b/kamon-system-metrics/src/main/scala/kamon/system/native/sigar-amd64-winnt.dll
index 1ec8a035..1ec8a035 100644
--- a/kamon-system/src/main/scala/kamon/system/native/sigar-amd64-winnt.dll
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/sigar-amd64-winnt.dll
Binary files differ
diff --git a/kamon-system/src/main/scala/kamon/system/native/sigar-x86-winnt.dll b/kamon-system-metrics/src/main/scala/kamon/system/native/sigar-x86-winnt.dll
index 6afdc016..6afdc016 100644
--- a/kamon-system/src/main/scala/kamon/system/native/sigar-x86-winnt.dll
+++ b/kamon-system-metrics/src/main/scala/kamon/system/native/sigar-x86-winnt.dll
Binary files differ
diff --git a/kamon-system-metrics/src/test/scala/kamon/metrics/SystemMetricsSpec.scala b/kamon-system-metrics/src/test/scala/kamon/metrics/SystemMetricsSpec.scala
new file mode 100644
index 00000000..ed10903f
--- /dev/null
+++ b/kamon-system-metrics/src/test/scala/kamon/metrics/SystemMetricsSpec.scala
@@ -0,0 +1,331 @@
+/* =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ * =========================================================================================
+ */
+
+package kamon.metric
+
+import akka.actor.ActorSystem
+import akka.testkit.{ TestKitBase, TestProbe }
+import com.typesafe.config.ConfigFactory
+import kamon.Kamon
+import kamon.metric.Subscriptions.TickMetricSnapshot
+import kamon.metrics.HeapMetrics.HeapMetricSnapshot
+import kamon.metrics.MemoryMetrics.MemoryMetricSnapshot
+import kamon.metrics.NetworkMetrics.NetworkMetricSnapshot
+import kamon.metrics.ProcessCPUMetrics.ProcessCPUMetricsSnapshot
+import kamon.metrics._
+import kamon.metrics.CPUMetrics.CPUMetricSnapshot
+import kamon.metrics.GCMetrics.GCMetricSnapshot
+import kamon.system.SystemMetricsExtension
+import org.scalatest.{ Matchers, WordSpecLike }
+
+import scala.concurrent.duration._
+
+class SystemMetricsSpec extends TestKitBase with WordSpecLike with Matchers {
+ implicit lazy val system: ActorSystem = ActorSystem("system-metrics-spec", ConfigFactory.parseString(
+ """
+ |akka {
+ | extensions = ["kamon.system.SystemMetrics"]
+ |}
+ |
+ |kamon.metrics {
+ |
+ | disable-aspectj-weaver-missing-error = true
+ |
+ | tick-interval = 1 second
+ |
+ | system {
+ | cpu {
+ | user {
+ | highest-trackable-value = 999999999
+ | significant-value-digits = 2
+ | }
+ | system {
+ | highest-trackable-value = 999999999
+ | significant-value-digits = 2
+ | }
+ | wait {
+ | highest-trackable-value = 999999999
+ | significant-value-digits = 2
+ | }
+ | idle {
+ | highest-trackable-value = 999999999
+ | significant-value-digits = 2
+ | }
+ | }
+ | process-cpu {
+ | user {
+ | highest-trackable-value = 999999999
+ | significant-value-digits = 2
+ | }
+ | system {
+ | highest-trackable-value = 999999999
+ | significant-value-digits = 2
+ | }
+ | }
+ | memory {
+ | used {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | free {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | buffer {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | cache {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | swap-used {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | swap-free {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | }
+ | network {
+ | rx-bytes {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | tx-bytes {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | rx-errors {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | tx-errors {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | }
+ | heap {
+ | used {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | max {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | committed {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | }
+ | gc {
+ | count {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | time {
+ | highest-trackable-value = 3600000000000
+ | significant-value-digits = 2
+ | }
+ | }
+ | }
+ |}
+ """.stripMargin))
+
+ "the Kamon CPU Metrics" should {
+ "record user, system, wait, idle metrics" in new CPUMetricsListenerFixture {
+ val metricsListener = subscribeToMetrics()
+
+ val CPUMetrics = expectCPUMetrics(metricsListener, 3 seconds)
+ CPUMetrics.user.max should be > 0L
+ CPUMetrics.system.max should be > 0L
+ CPUMetrics.cpuWait.max should be > 0L
+ CPUMetrics.idle.max should be > 0L
+ }
+ }
+ "the Kamon GC Metrics" should {
+ "record count, time metrics" in new GCMetricsListenerFixture {
+ val metricsListener = subscribeToMetrics()
+
+ val GCMetrics = expectGCMetrics(metricsListener, 3 seconds)
+ GCMetrics.count.max should be > 0L
+ GCMetrics.time.max should be > 0L
+ }
+ }
+
+ "the Kamon Heap Metrics" should {
+ "record used, max, commited metrics" in new HeapMetricsListenerFixture {
+ val metricsListener = subscribeToMetrics()
+
+ val HeapMetrics = expectHeapMetrics(metricsListener, 3 seconds)
+ HeapMetrics.used.max should be >= 0L
+ HeapMetrics.max.max should be >= 0L
+ HeapMetrics.committed.max should be >= 0L
+ }
+ }
+
+ "the Kamon Memory Metrics" should {
+ "record used, free, buffer, cache, swap used, swap free metrics" in new MemoryMetricsListenerFixture {
+ val metricsListener = subscribeToMetrics()
+
+ val MemoryMetrics = expectMemoryMetrics(metricsListener, 3 seconds)
+ MemoryMetrics.used.max should be >= 0L
+ MemoryMetrics.free.max should be >= 0L
+ MemoryMetrics.buffer.max should be >= 0L
+ MemoryMetrics.cache.max should be >= 0L
+ MemoryMetrics.swapUsed.max should be >= 0L
+ MemoryMetrics.swapFree.max should be >= 0L
+ }
+ }
+
+ "the Kamon Network Metrics" should {
+ "record rxBytes, txBytes, rxErrors, txErrors metrics" in new NetworkMetricsListenerFixture {
+ val metricsListener = subscribeToMetrics()
+
+ val NetworkMetrics = expectNetworkMetrics(metricsListener, 3 seconds)
+ NetworkMetrics.rxBytes.max should be >= 0L
+ NetworkMetrics.txBytes.max should be >= 0L
+ NetworkMetrics.rxErrors.max should be >= 0L
+ NetworkMetrics.txErrors.max should be >= 0L
+ }
+ }
+
+ "the Kamon Process CPU Metrics" should {
+ "record user, system metrics" in new ProcessCPUMetricsListenerFixture {
+ val metricsListener = subscribeToMetrics()
+
+ val ProcessCPUMetrics = expectProcessCPUMetrics(metricsListener, 3 seconds)
+ ProcessCPUMetrics.user.max should be > 0L
+ ProcessCPUMetrics.system.max should be > 0L
+ }
+ }
+
+ def expectCPUMetrics(listener: TestProbe, waitTime: FiniteDuration): CPUMetricSnapshot = {
+ val tickSnapshot = within(waitTime) {
+ listener.expectMsgType[TickMetricSnapshot]
+ }
+ val cpuMetricsOption = tickSnapshot.metrics.get(CPUMetrics(SystemMetricsExtension.CPU))
+ cpuMetricsOption should not be empty
+ cpuMetricsOption.get.asInstanceOf[CPUMetricSnapshot]
+ }
+
+ trait CPUMetricsListenerFixture {
+ def subscribeToMetrics(): TestProbe = {
+ val metricsListener = TestProbe()
+ Kamon(Metrics).subscribe(CPUMetrics, "*", metricsListener.ref, permanently = true)
+ // Wait for one empty snapshot before proceeding to the test.
+ metricsListener.expectMsgType[TickMetricSnapshot]
+ metricsListener
+ }
+ }
+
+ def expectGCMetrics(listener: TestProbe, waitTime: FiniteDuration): GCMetricSnapshot = {
+ val tickSnapshot = within(waitTime) {
+ listener.expectMsgType[TickMetricSnapshot]
+ }
+
+ val gcMetricsOption = tickSnapshot.metrics.get(GCMetrics(SystemMetricsExtension.garbageCollectors(0).getName))
+ gcMetricsOption should not be empty
+ gcMetricsOption.get.asInstanceOf[GCMetricSnapshot]
+ }
+
+ trait GCMetricsListenerFixture {
+ def subscribeToMetrics(): TestProbe = {
+ val metricsListener = TestProbe()
+ Kamon(Metrics).subscribe(GCMetrics, "*", metricsListener.ref, permanently = true)
+ // Wait for one empty snapshot before proceeding to the test.
+ metricsListener.expectMsgType[TickMetricSnapshot]
+ metricsListener
+ }
+ }
+
+ def expectHeapMetrics(listener: TestProbe, waitTime: FiniteDuration): HeapMetricSnapshot = {
+ val tickSnapshot = within(waitTime) {
+ listener.expectMsgType[TickMetricSnapshot]
+ }
+ val heapMetricsOption = tickSnapshot.metrics.get(HeapMetrics(SystemMetricsExtension.Heap))
+ heapMetricsOption should not be empty
+ heapMetricsOption.get.asInstanceOf[HeapMetricSnapshot]
+ }
+
+ trait HeapMetricsListenerFixture {
+ def subscribeToMetrics(): TestProbe = {
+ val metricsListener = TestProbe()
+ Kamon(Metrics).subscribe(HeapMetrics, "*", metricsListener.ref, permanently = true)
+ // Wait for one empty snapshot before proceeding to the test.
+ metricsListener.expectMsgType[TickMetricSnapshot]
+ metricsListener
+ }
+ }
+
+ def expectMemoryMetrics(listener: TestProbe, waitTime: FiniteDuration): MemoryMetricSnapshot = {
+ val tickSnapshot = within(waitTime) {
+ listener.expectMsgType[TickMetricSnapshot]
+ }
+ val memoryMetricsOption = tickSnapshot.metrics.get(MemoryMetrics(SystemMetricsExtension.Memory))
+ memoryMetricsOption should not be empty
+ memoryMetricsOption.get.asInstanceOf[MemoryMetricSnapshot]
+ }
+
+ trait MemoryMetricsListenerFixture {
+ def subscribeToMetrics(): TestProbe = {
+ val metricsListener = TestProbe()
+ Kamon(Metrics).subscribe(MemoryMetrics, "*", metricsListener.ref, permanently = true)
+ // Wait for one empty snapshot before proceeding to the test.
+ metricsListener.expectMsgType[TickMetricSnapshot]
+ metricsListener
+ }
+ }
+
+ def expectNetworkMetrics(listener: TestProbe, waitTime: FiniteDuration): NetworkMetricSnapshot = {
+ val tickSnapshot = within(waitTime) {
+ listener.expectMsgType[TickMetricSnapshot]
+ }
+ val networkMetricsOption = tickSnapshot.metrics.get(NetworkMetrics(SystemMetricsExtension.Network))
+ networkMetricsOption should not be empty
+ networkMetricsOption.get.asInstanceOf[NetworkMetricSnapshot]
+ }
+
+ trait NetworkMetricsListenerFixture {
+ def subscribeToMetrics(): TestProbe = {
+ val metricsListener = TestProbe()
+ Kamon(Metrics).subscribe(NetworkMetrics, "*", metricsListener.ref, permanently = true)
+ // Wait for one empty snapshot before proceeding to the test.
+ metricsListener.expectMsgType[TickMetricSnapshot]
+ metricsListener
+ }
+ }
+
+ def expectProcessCPUMetrics(listener: TestProbe, waitTime: FiniteDuration): ProcessCPUMetricsSnapshot = {
+ val tickSnapshot = within(waitTime) {
+ listener.expectMsgType[TickMetricSnapshot]
+ }
+ val processCPUMetricsOption = tickSnapshot.metrics.get(ProcessCPUMetrics(SystemMetricsExtension.ProcessCPU))
+ processCPUMetricsOption should not be empty
+ processCPUMetricsOption.get.asInstanceOf[ProcessCPUMetricsSnapshot]
+ }
+
+ trait ProcessCPUMetricsListenerFixture {
+ def subscribeToMetrics(): TestProbe = {
+ val metricsListener = TestProbe()
+ Kamon(Metrics).subscribe(ProcessCPUMetrics, "*", metricsListener.ref, permanently = true)
+ // Wait for one empty snapshot before proceeding to the test.
+ metricsListener.expectMsgType[TickMetricSnapshot]
+ metricsListener
+ }
+ }
+}
diff --git a/kamon-system/src/main/resources/reference.conf b/kamon-system/src/main/resources/reference.conf
deleted file mode 100644
index 94d28106..00000000
--- a/kamon-system/src/main/resources/reference.conf
+++ /dev/null
@@ -1,28 +0,0 @@
-# ==================================== #
-# Kamon-System Reference Configuration #
-# ==================================== #
-
-kamon {
- precision {
- system {
- processing-time {
- highest-trackable-value = 3600000000000
- significant-value-digits = 2
- }
- time-in-mailbox {
- highest-trackable-value = 3600000000000
- significant-value-digits = 2
- }
- mailbox-size {
- highest-trackable-value = 999999999
- significant-value-digits = 2
- }
- }
- jvm {
- processing-time {
- highest-trackable-value = 3600000000000
- significant-value-digits = 2
- }
- }
- }
-} \ No newline at end of file
diff --git a/kamon-system/src/main/scala/kamon/metrics/CpuMetricsCollector.scala b/kamon-system/src/main/scala/kamon/metrics/CpuMetricsCollector.scala
deleted file mode 100644
index 17f6fb08..00000000
--- a/kamon-system/src/main/scala/kamon/metrics/CpuMetricsCollector.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-package kamon.metrics
-
-import kamon.system.native.SigarLoader
-import org.hyperic.sigar.{NetInterfaceStat, Swap}
-
-trait SigarExtensionProvider {
- self: MetricsCollector =>
-
- lazy val sigar = SigarLoader.init
-}
-
-trait MetricsCollector extends SigarExtensionProvider {
- def collect: MetricsMeasurement
-}
-
-sealed trait MetricsMeasurement
-case class MemoryMetricsMeasurement(memUsage: Long, memSwapPageIn: Long, memSwapPageOut: Long) extends MetricsMeasurement
-case class NetworkMetricsMeasurement(tcpCurrEstab: Long,
- tcpEstabResets: Long,
- netRxBytesRate: Long,
- netTxBytesRate: Long,
- netRxErrors: Long,
- netTxErrors: Long) extends MetricsMeasurement
-
-case class CpuMetricsMeasurement(cpuUser: Long, cpuSys: Long, cpuCombined: Long,
- loadAverage1min: Long,
- loadAverage5min: Long,
- loadAverage15min: Long) extends MetricsMeasurement
-
-
-
-class CpuMetricsCollector extends MetricsCollector {
- val loadAverage = sigar.getLoadAverage
- val cpuPerc = sigar.getCpuPerc
-
-
- def collect(): CpuMetricsMeasurement = {
- println(s"ProcCPU->${sigar.getProcCpu(sigar.getPid)}")
- val loadAverage1min = loadAverage(0).toLong
- val loadAverage5min = loadAverage(1).toLong
- val loadAverage15min = loadAverage(2).toLong
-
- CpuMetricsMeasurement(cpuPerc.getUser.toLong, cpuPerc.getSys.toLong, cpuPerc.getCombined.toLong, loadAverage1min, loadAverage5min, loadAverage15min)
- }
-}
-
-class MemoryMetricsCollector extends MetricsCollector {
- val swap: Swap = sigar.getSwap
-
- def collect(): MetricsMeasurement = MemoryMetricsMeasurement(sigar.getMem.getUsedPercent.toLong, swap.getPageIn, swap.getPageOut)
-}
-
-class NetWorkMetricsCollector extends MetricsCollector {
- val interfaces = sigar.getNetInterfaceList.toSet
- val tcp = sigar.getTcp
-
- var netRxBytes = 0L
- var netTxBytes = 0L
- var netRxErrors = 0L
- var netTxErrors = 0L
-
- def collect(): MetricsMeasurement = {
- for{
- interface <- interfaces
- net:NetInterfaceStat <- sigar.getNetInterfaceStat(interface)
- }{
- netRxBytes += net.getRxBytes
- netTxBytes += net.getTxBytes
- netRxErrors += net.getRxErrors
- netTxErrors += net.getTxErrors
- }
- NetworkMetricsMeasurement(tcp.getCurrEstab, tcp.getEstabResets,netRxBytes, netTxBytes, netRxErrors, netTxErrors)
- }
-} \ No newline at end of file
diff --git a/kamon-system/src/main/scala/kamon/metrics/JvmMetrics.scala b/kamon-system/src/main/scala/kamon/metrics/JvmMetrics.scala
deleted file mode 100644
index fb3bfeb8..00000000
--- a/kamon-system/src/main/scala/kamon/metrics/JvmMetrics.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * =========================================================================================
- * Copyright © 2013-2014 the kamon project <http://kamon.io/>
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language governing permissions
- * and limitations under the License.
- * =========================================================================================
- */
-
-package kamon.metrics
-
-import com.typesafe.config.Config
-import org.HdrHistogram.HdrRecorder
-
-case class JvmMetrics(name: String) extends MetricGroupIdentity {
- val category = JvmMetrics
-}
-
-object JvmMetrics extends MetricGroupCategory {
- val name = "system"
-
- case object MaximumPoolSize extends MetricIdentity { val name, tag = "maximum-pool-size" }
- case object RunningThreadCount extends MetricIdentity { val name, tag = "running-thread-count" }
- case object QueueTaskCount extends MetricIdentity { val name, tag = "queued-task-count" }
- case object PoolSize extends MetricIdentity { val name, tag = "pool-size" }
-
- case class JvmMetricRecorder(maximumPoolSize: MetricRecorder, runningThreadCount: MetricRecorder, queueTaskCount: MetricRecorder, poolSize: MetricRecorder)
- extends MetricGroupRecorder {
-
- def collect: MetricGroupSnapshot = {
- JvmMetricSnapshot(maximumPoolSize.collect(), runningThreadCount.collect(), queueTaskCount.collect(), poolSize.collect())
- }
- }
-
- case class JvmMetricSnapshot(maximumPoolSize: MetricSnapshotLike, runningThreadCount: MetricSnapshotLike, queueTaskCount: MetricSnapshotLike, poolSize: MetricSnapshotLike)
- extends MetricGroupSnapshot {
-
- val metrics: Map[MetricIdentity, MetricSnapshotLike] = Map(
- (MaximumPoolSize -> maximumPoolSize),
- (RunningThreadCount -> runningThreadCount),
- (QueueTaskCount -> queueTaskCount),
- (PoolSize -> poolSize))
- }
-
- val Factory = new MetricGroupFactory {
- type GroupRecorder = JvmMetricRecorder
-
- def create(config: Config): JvmMetricRecorder = {
- val settings = config.getConfig("precision.jvm")
-
- val threadCountConfig = extractPrecisionConfig(settings.getConfig("maximum-pool-size"))
- val RunningThreadCountConfig = extractPrecisionConfig(settings.getConfig("running-thread-count"))
- val QueueTaskCountConfig = extractPrecisionConfig(settings.getConfig("queued-task-count"))
- val PoolSizeConfig = extractPrecisionConfig(settings.getConfig("pool-size"))
-
- new JvmMetricRecorder(
- HdrRecorder(threadCountConfig.highestTrackableValue, threadCountConfig.significantValueDigits, Scale.Unit),
- HdrRecorder(RunningThreadCountConfig.highestTrackableValue, RunningThreadCountConfig.significantValueDigits, Scale.Unit),
- HdrRecorder(QueueTaskCountConfig.highestTrackableValue, QueueTaskCountConfig.significantValueDigits, Scale.Unit),
- HdrRecorder(PoolSizeConfig.highestTrackableValue, PoolSizeConfig.significantValueDigits, Scale.Unit))
- }
- }
-}
-
diff --git a/kamon-system/src/main/scala/kamon/metrics/SystemMetrics.scala b/kamon-system/src/main/scala/kamon/metrics/SystemMetrics.scala
deleted file mode 100644
index 9bcd8917..00000000
--- a/kamon-system/src/main/scala/kamon/metrics/SystemMetrics.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * =========================================================================================
- * Copyright © 2013-2014 the kamon project <http://kamon.io/>
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language governing permissions
- * and limitations under the License.
- * =========================================================================================
- */
-
-package kamon.metrics
-
-import com.typesafe.config.Config
-import org.HdrHistogram.HdrRecorder
-
-case class SystemMetrics(name: String) extends MetricGroupIdentity {
- val category = JvmMetrics
-}
-
-object SystemMetrics extends MetricGroupCategory {
- val name = "system"
-
- case object MaximumPoolSize extends MetricIdentity { val name, tag = "maximum-pool-size" }
- case object RunningThreadCount extends MetricIdentity { val name, tag = "running-thread-count" }
- case object QueueTaskCount extends MetricIdentity { val name, tag = "queued-task-count" }
- case object PoolSize extends MetricIdentity { val name, tag = "pool-size" }
-
- case class SystemMetricRecorder(maximumPoolSize: MetricRecorder, runningThreadCount: MetricRecorder, queueTaskCount: MetricRecorder, poolSize: MetricRecorder)
- extends MetricGroupRecorder {
-
- def collect: MetricGroupSnapshot = {
- SystemMetricSnapshot(maximumPoolSize.collect(), runningThreadCount.collect(), queueTaskCount.collect(), poolSize.collect())
- }
- }
-
- case class SystemMetricSnapshot(maximumPoolSize: MetricSnapshotLike, runningThreadCount: MetricSnapshotLike, queueTaskCount: MetricSnapshotLike, poolSize: MetricSnapshotLike)
- extends MetricGroupSnapshot {
-
- val metrics: Map[MetricIdentity, MetricSnapshotLike] = Map(
- (MaximumPoolSize -> maximumPoolSize),
- (RunningThreadCount -> runningThreadCount),
- (QueueTaskCount -> queueTaskCount),
- (PoolSize -> poolSize))
- }
-
- val Factory = new MetricGroupFactory {
- type GroupRecorder = SystemMetricRecorder
-
- def create(config: Config): SystemMetricRecorder = {
- val settings = config.getConfig("precision.system")
-
- val threadCountConfig = extractPrecisionConfig(settings.getConfig("maximum-pool-size"))
- val RunningThreadCountConfig = extractPrecisionConfig(settings.getConfig("running-thread-count"))
- val QueueTaskCountConfig = extractPrecisionConfig(settings.getConfig("queued-task-count"))
- val PoolSizeConfig = extractPrecisionConfig(settings.getConfig("pool-size"))
-
- new SystemMetricRecorder(
- HdrRecorder(threadCountConfig.highestTrackableValue, threadCountConfig.significantValueDigits, Scale.Unit),
- HdrRecorder(RunningThreadCountConfig.highestTrackableValue, RunningThreadCountConfig.significantValueDigits, Scale.Unit),
- HdrRecorder(QueueTaskCountConfig.highestTrackableValue, QueueTaskCountConfig.significantValueDigits, Scale.Unit),
- HdrRecorder(PoolSizeConfig.highestTrackableValue, PoolSizeConfig.significantValueDigits, Scale.Unit))
- }
- }
-}
-
diff --git a/kamon-system/src/main/scala/kamon/system/System.scala b/kamon-system/src/main/scala/kamon/system/System.scala
deleted file mode 100644
index a6c468ef..00000000
--- a/kamon-system/src/main/scala/kamon/system/System.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * =========================================================================================
- * Copyright © 2013-2014 the kamon project <http://kamon.io/>
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language governing permissions
- * and limitations under the License.
- * =========================================================================================
- */
-
-package kamon.system
-
-import akka.actor.{ ExtendedActorSystem, Extension, ExtensionIdProvider, ExtensionId }
-import kamon.Kamon
-import akka.event.Logging
-
-object System extends ExtensionId[SystemExtension] with ExtensionIdProvider {
- override def lookup(): ExtensionId[_ <: Extension] = System
- override def createExtension(system: ExtendedActorSystem): SystemExtension = new SystemExtension(system)
-}
-
-class SystemExtension(private val system: ExtendedActorSystem) extends Kamon.Extension {
- val log = Logging(system, classOf[SystemExtension])
- log.info("Starting the Kamon(System) extension")
-
- private val config = system.settings.config.getConfig("kamon.system")
-
- val defaultDispatcher = system.dispatchers.lookup(config.getString("dispatcher"))
-}
-
diff --git a/kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala b/kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala
deleted file mode 100644
index 511a8ffc..00000000
--- a/kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package kamon.system.native
-
-import org.hyperic.sigar.Sigar
-import org.hyperic.sigar.SigarProxy
-import java.io._
-import scalax.io.JavaConverters._
-import scalax.io._
-
-import Resource._
-
-import scalax.file.Path
-import java.util
-import scala.collection.JavaConversions._
-
-object SigarLoader {
- val Version = "1.6.4"
- val JavaLibraryPath = "java.library.path"
- val TmpDir = "java.io.tmpdir"
- val IndexFile = "/kamon/system/native/index"
- val UsrPathField = "usr_paths"
-
- def init: SigarProxy = init(new File(System.getProperty(TmpDir)))
-
- private def init(baseTmp: File): SigarProxy = {
- val tmpDir = createTmpDir(baseTmp)
- for (lib ← loadIndex) copy(lib, tmpDir)
-
- attachToLibraryPath(tmpDir)
-
- try {
- val sigar = new Sigar
- sigar.getPid
- sigar
- } catch {
- case t: Throwable ⇒
- throw new RuntimeException("Failed to load sigar", t)
- }
- }
-
- private val usrPathField = {
- val usrPathField = classOf[ClassLoader].getDeclaredField(UsrPathField)
- usrPathField.setAccessible(true)
- usrPathField
- }
-
- private def attachToLibraryPath(dir: File): Unit = {
- val dirAbsolute = dir.getAbsolutePath
- System.setProperty(JavaLibraryPath, newLibraryPath(dirAbsolute))
- var paths = usrPathField.get(null).asInstanceOf[Array[String]]
- if (paths == null) paths = new Array[String](0)
- for (path ← paths) if (path == dirAbsolute) return
- val newPaths = util.Arrays.copyOf(paths, paths.length + 1)
- newPaths(newPaths.length - 1) = dirAbsolute
- usrPathField.set(null, newPaths)
- }
-
- private def newLibraryPath(dirAbsolutePath: String): String = {
- Option(System.getProperty(JavaLibraryPath)).fold(dirAbsolutePath)(oldValue ⇒ s"$dirAbsolutePath${File.pathSeparator}$oldValue")
- }
-
- private def copy(lib: String, tmpDir: File) {
- val dest: Path = Path(new File(tmpDir, lib))
- if (dest.exists) return
- val currentFile = Resource.fromInputStream(classOf[Loader].getResourceAsStream("" + lib))
- currentFile.acquireFor(current ⇒ dest.doCopyFrom(current.asInput))
- }
-
- private def createTmpDir(baseTmp: File): File = {
- val path = Path(new File(baseTmp, s"sigar-$Version"))
- path.createDirectory(failIfExists = false)
- path.jfile
- }
-
- private def loadIndex: util.List[String] = {
- val libs = new util.ArrayList[String]
- val input = fromInputStream(classOf[Loader].getResourceAsStream(IndexFile))
- input.lines().foreach(libs.add)
- libs
- }
-}
-
-class Loader \ No newline at end of file
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 78240abe..1b67d214 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -37,8 +37,6 @@ object Dependencies {
val jsr166 = "io.gatling" % "jsr166e" % "1.0"
val scalaCompiler = "org.scala-lang" % "scala-compiler" % Settings.ScalaVersion
val sigar = "org.fusesource" % "sigar" % "1.6.4"
- val ioCore = "com.github.scala-incubator.io" %% "scala-io-core" % "0.4.3"
- val ioFile = "com.github.scala-incubator.io" %% "scala-io-file" % "0.4.3"
def compile (deps: ModuleID*): Seq[ModuleID] = deps map (_ % "compile")
def provided (deps: ModuleID*): Seq[ModuleID] = deps map (_ % "provided")
diff --git a/project/Projects.scala b/project/Projects.scala
index 768ac6d8..dd44f6bc 100644
--- a/project/Projects.scala
+++ b/project/Projects.scala
@@ -7,7 +7,7 @@ object Projects extends Build {
import Dependencies._
lazy val root = Project("root", file("."))
- .aggregate(kamonCore, kamonSpray, kamonNewrelic, kamonPlayground, kamonDashboard, kamonTestkit, kamonPlay, kamonStatsD, kamonDatadog)
+ .aggregate(kamonCore, kamonSpray, kamonNewrelic, kamonPlayground, kamonDashboard, kamonTestkit, kamonPlay, kamonStatsD, kamonDatadog, kamonSystemMetrics)
.settings(basicSettings: _*)
.settings(formatSettings: _*)
.settings(noPublishing: _*)
@@ -57,7 +57,7 @@ object Projects extends Build {
.settings(
libraryDependencies ++=
compile(akkaActor, akkaSlf4j, sprayCan, sprayClient, sprayRouting, logback))
- .dependsOn(kamonSpray, kamonNewrelic, kamonStatsD, kamonDatadog)
+ .dependsOn(kamonSpray, kamonNewrelic, kamonStatsD, kamonDatadog, kamonSystemMetrics)
lazy val kamonDashboard = Project("kamon-dashboard", file("kamon-dashboard"))
@@ -85,12 +85,14 @@ object Projects extends Build {
.settings(formatSettings: _*)
.settings(libraryDependencies ++= compile(akkaActor) ++ test(scalatest, akkaTestKit, slf4Api, slf4nop))
.dependsOn(kamonCore)
+ .dependsOn(kamonSystemMetrics % "provided")
lazy val kamonDatadog = Project("kamon-datadog", file("kamon-datadog"))
.settings(basicSettings: _*)
.settings(formatSettings: _*)
- .settings(libraryDependencies ++= compile(akkaActor) ++ test(scalatest, akkaTestKit, slf4Api, slf4nop))
+ .settings(libraryDependencies ++= compile(akkaActor) ++ test(scalatest, akkaTestKit, slf4Api, slf4nop))
.dependsOn(kamonCore)
+ .dependsOn(kamonSystemMetrics % "provided")
lazy val kamonMacros = Project("kamon-macros", file("kamon-macros"))
.settings(basicSettings: _*)
@@ -98,5 +100,11 @@ object Projects extends Build {
.settings(noPublishing: _*)
.settings(libraryDependencies ++= compile(scalaCompiler))
+ lazy val kamonSystemMetrics = Project("kamon-system-metrics", file("kamon-system-metrics"))
+ .settings(basicSettings: _*)
+ .settings(formatSettings: _*)
+ .settings(libraryDependencies ++= compile(sigar) ++ test(scalatest, akkaTestKit, slf4Api, slf4nop))
+ .dependsOn(kamonCore)
+
val noPublishing = Seq(publish := (), publishLocal := (), publishArtifact := false)
}