aboutsummaryrefslogtreecommitdiff
path: root/kamon-system-metrics/src/main/scala/kamon
diff options
context:
space:
mode:
Diffstat (limited to 'kamon-system-metrics/src/main/scala/kamon')
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala88
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/ClassLoadingMetrics.scala85
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/ContextSwitchesMetrics.scala81
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/DiskMetrics.scala85
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala77
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala87
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/LoadAverageMetrics.scala80
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala92
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/NetworkMetrics.scala91
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/NonHeapMetrics.scala86
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala76
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/metrics/ThreadMetrics.scala85
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/GcMetricsCollector.scala77
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala78
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsBanner.scala91
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsCollector.scala266
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsExtension.scala70
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/custom/ContextSwitchesMetrics.scala96
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/jmx/ClassLoadingMetrics.scala28
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala34
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/jmx/HeapMemoryMetrics.scala29
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala13
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/jmx/NonHeapMemoryMetrics.scala33
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/jmx/ThreadsMetrics.scala28
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/CpuMetrics.scala29
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/DiffRecordingHistogram.scala41
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/FileSystemMetrics.scala25
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/LoadAverageMetrics.scala25
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/MemoryMetrics.scala36
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/NetworkMetrics.scala33
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/ProcessCpuMetrics.scala39
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala59
32 files changed, 618 insertions, 1525 deletions
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala
deleted file mode 100644
index 20789039..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/CPUMetrics.scala
+++ /dev/null
@@ -1,88 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-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 object Stolen extends MetricIdentity { val name = "stolen" }
-
- case class CPUMetricRecorder(user: Histogram, system: Histogram, cpuWait: Histogram, idle: Histogram, stolen: Histogram)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- CPUMetricSnapshot(user.collect(context), system.collect(context), cpuWait.collect(context), idle.collect(context), stolen.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class CPUMetricSnapshot(user: Histogram.Snapshot, system: Histogram.Snapshot, cpuWait: Histogram.Snapshot, idle: Histogram.Snapshot, stolen: 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), stolen.merge(that.stolen, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- User -> user,
- System -> system,
- Wait -> cpuWait,
- Idle -> idle,
- Stolen -> stolen)
- }
-
- val Factory = CPUMetricGroupFactory
-}
-
-case object CPUMetricGroupFactory extends MetricGroupFactory {
-
- import CPUMetrics._
-
- 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")
- val stolenConfig = settings.getConfig("stolen")
-
- new CPUMetricRecorder(
- Histogram.fromConfig(userConfig),
- Histogram.fromConfig(systemConfig),
- Histogram.fromConfig(cpuWaitConfig),
- Histogram.fromConfig(idleConfig),
- Histogram.fromConfig(stolenConfig))
- }
-}
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/ClassLoadingMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/ClassLoadingMetrics.scala
deleted file mode 100644
index 1e3bee27..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/ClassLoadingMetrics.scala
+++ /dev/null
@@ -1,85 +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 java.lang.management.ManagementFactory
-
-import akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.{ Gauge, Histogram }
-
-case class ClassLoadingMetrics(name: String) extends MetricGroupIdentity {
- val category = ClassLoadingMetrics
-}
-
-object ClassLoadingMetrics extends MetricGroupCategory {
- val name = "classes"
-
- case object Loaded extends MetricIdentity { val name = "total-loaded" }
- case object Unloaded extends MetricIdentity { val name = "total-unloaded" }
- case object Current extends MetricIdentity { val name = "current-loaded" }
-
- case class ClassLoadingMetricRecorder(loaded: Gauge, unloaded: Gauge, current: Gauge)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- ClassLoadingMetricSnapshot(loaded.collect(context), unloaded.collect(context), current.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class ClassLoadingMetricSnapshot(loaded: Histogram.Snapshot, unloaded: Histogram.Snapshot, current: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = ClassLoadingMetricSnapshot
-
- def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
- ClassLoadingMetricSnapshot(loaded.merge(that.loaded, context), unloaded.merge(that.unloaded, context), current.merge(that.current, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- Loaded -> loaded,
- Unloaded -> unloaded,
- Current -> current)
- }
-
- val Factory = ClassLoadingMetricGroupFactory
-}
-
-case object ClassLoadingMetricGroupFactory extends MetricGroupFactory {
-
- import ClassLoadingMetrics._
-
- val classes = ManagementFactory.getClassLoadingMXBean
-
- type GroupRecorder = ClassLoadingMetricRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.jvm.classes")
-
- val totalLoadedConfig = settings.getConfig("total-loaded")
- val totalUnloadedConfig = settings.getConfig("total-unloaded")
- val currentLoadedConfig = settings.getConfig("current-loaded")
-
- new ClassLoadingMetricRecorder(
- Gauge.fromConfig(totalLoadedConfig, system)(() ⇒ classes.getTotalLoadedClassCount),
- Gauge.fromConfig(totalUnloadedConfig, system)(() ⇒ classes.getUnloadedClassCount),
- Gauge.fromConfig(currentLoadedConfig, system)(() ⇒ classes.getLoadedClassCount.toLong))
- }
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/ContextSwitchesMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/ContextSwitchesMetrics.scala
deleted file mode 100644
index 86aeabce..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/ContextSwitchesMetrics.scala
+++ /dev/null
@@ -1,81 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-case class ContextSwitchesMetrics(name: String) extends MetricGroupIdentity {
- val category = ContextSwitchesMetrics
-}
-
-object ContextSwitchesMetrics extends MetricGroupCategory {
- val name = "context-switches"
-
- case object PerProcessVoluntary extends MetricIdentity { val name = "per-process-voluntary" }
- case object PerProcessNonVoluntary extends MetricIdentity { val name = "per-process-non-voluntary" }
- case object Global extends MetricIdentity { val name = "global" }
-
- case class ContextSwitchesMetricsRecorder(perProcessVoluntary: Histogram, perProcessNonVoluntary: Histogram, global: Histogram)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- ContextSwitchesMetricsSnapshot(perProcessVoluntary.collect(context), perProcessNonVoluntary.collect(context), global.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class ContextSwitchesMetricsSnapshot(perProcessVoluntary: Histogram.Snapshot, perProcessNonVoluntary: Histogram.Snapshot, global: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = ContextSwitchesMetricsSnapshot
-
- def merge(that: ContextSwitchesMetricsSnapshot, context: CollectionContext): GroupSnapshotType = {
- ContextSwitchesMetricsSnapshot(perProcessVoluntary.merge(that.perProcessVoluntary, context), perProcessVoluntary.merge(that.perProcessVoluntary, context), global.merge(that.global, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- PerProcessVoluntary -> perProcessVoluntary,
- PerProcessNonVoluntary -> perProcessNonVoluntary,
- Global -> global)
- }
-
- val Factory = ContextSwitchesMetricGroupFactory
-}
-
-case object ContextSwitchesMetricGroupFactory extends MetricGroupFactory {
- import ContextSwitchesMetrics._
-
- type GroupRecorder = ContextSwitchesMetricsRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.system.context-switches")
-
- val perProcessVoluntary = settings.getConfig("per-process-voluntary")
- val perProcessNonVoluntary = settings.getConfig("per-process-non-voluntary")
- val global = settings.getConfig("global")
-
- new ContextSwitchesMetricsRecorder(
- Histogram.fromConfig(perProcessVoluntary),
- Histogram.fromConfig(perProcessNonVoluntary),
- Histogram.fromConfig(global))
- }
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/DiskMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/DiskMetrics.scala
deleted file mode 100644
index eeb6002b..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/DiskMetrics.scala
+++ /dev/null
@@ -1,85 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-case class DiskMetrics(name: String) extends MetricGroupIdentity {
- val category = DiskMetrics
-}
-
-object DiskMetrics extends MetricGroupCategory {
- val name = "disk"
-
- case object Reads extends MetricIdentity { val name = "reads" }
- case object Writes extends MetricIdentity { val name = "writes" }
- case object Queue extends MetricIdentity { val name = "queue" }
- case object ServiceTime extends MetricIdentity { val name = "service-time" }
-
- case class DiskMetricsRecorder(reads: Histogram, writes: Histogram, queue: Histogram, serviceTime: Histogram)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- DiskMetricsSnapshot(reads.collect(context), writes.collect(context), queue.collect(context), serviceTime.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class DiskMetricsSnapshot(reads: Histogram.Snapshot, writes: Histogram.Snapshot, queue: Histogram.Snapshot, serviceTime: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = DiskMetricsSnapshot
-
- def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
- DiskMetricsSnapshot(reads.merge(that.reads, context), writes.merge(that.writes, context), queue.merge(that.queue, context), serviceTime.merge(that.serviceTime, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- Reads -> reads,
- Writes -> writes,
- Queue -> queue,
- ServiceTime -> serviceTime)
- }
-
- val Factory = DiskMetricGroupFactory
-}
-
-case object DiskMetricGroupFactory extends MetricGroupFactory {
-
- import DiskMetrics._
-
- type GroupRecorder = DiskMetricsRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.system.disk")
-
- val readsDiskConfig = settings.getConfig("reads")
- val writesDiskConfig = settings.getConfig("writes")
- val queueDiskConfig = settings.getConfig("queue")
- val serviceTimeDiskConfig = settings.getConfig("service-time")
-
- new DiskMetricsRecorder(
- Histogram.fromConfig(readsDiskConfig),
- Histogram.fromConfig(writesDiskConfig),
- Histogram.fromConfig(queueDiskConfig),
- Histogram.fromConfig(serviceTimeDiskConfig))
- }
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala
deleted file mode 100644
index 5aa679c9..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/GCMetrics.scala
+++ /dev/null
@@ -1,77 +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 java.lang.management.GarbageCollectorMXBean
-
-import akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.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: Histogram, time: Histogram)
- 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) = GCMetricGroupFactory(gc)
-}
-
-case class GCMetricGroupFactory(gc: GarbageCollectorMXBean) extends MetricGroupFactory {
- import GCMetrics._
-
- 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(
- Histogram.fromConfig(countConfig),
- Histogram.fromConfig(timeConfig))
- }
-} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala
deleted file mode 100644
index 5bba5bf6..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/HeapMetrics.scala
+++ /dev/null
@@ -1,87 +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 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" }
- case object Max extends MetricIdentity { val name = "max" }
- case object Committed extends MetricIdentity { val name = "committed" }
-
- 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 = HeapMetricGroupFactory
-}
-
-case object HeapMetricGroupFactory extends MetricGroupFactory {
-
- import HeapMetrics._
- import kamon.system.SystemMetricsExtension._
-
- def heap = ManagementFactory.getMemoryMXBean.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, Scale.Mega)(() ⇒ toMB(heap.getUsed)),
- Gauge.fromConfig(maxHeapConfig, system, Scale.Mega)(() ⇒ toMB(heap.getMax)),
- Gauge.fromConfig(committedHeapConfig, system, Scale.Mega)(() ⇒ toMB(heap.getCommitted)))
- }
-
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/LoadAverageMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/LoadAverageMetrics.scala
deleted file mode 100644
index cd196adf..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/LoadAverageMetrics.scala
+++ /dev/null
@@ -1,80 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-case class LoadAverageMetrics(name: String) extends MetricGroupIdentity {
- val category = LoadAverageMetrics
-}
-
-object LoadAverageMetrics extends MetricGroupCategory {
- val name = "load-average"
-
- case object OneMinute extends MetricIdentity { val name = "last-minute" }
- case object FiveMinutes extends MetricIdentity { val name = "last-five-minutes" }
- case object FifteenMinutes extends MetricIdentity { val name = "last-fifteen-minutes" }
-
- case class LoadAverageMetricsRecorder(one: Histogram, five: Histogram, fifteen: Histogram)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- LoadAverageMetricsSnapshot(one.collect(context), five.collect(context), fifteen.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class LoadAverageMetricsSnapshot(one: Histogram.Snapshot, five: Histogram.Snapshot, fifteen: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = LoadAverageMetricsSnapshot
-
- def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
- LoadAverageMetricsSnapshot(one.merge(that.one, context), five.merge(that.five, context), fifteen.merge(that.fifteen, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- OneMinute -> one,
- FiveMinutes -> five,
- FifteenMinutes -> fifteen)
- }
-
- val Factory = LoadAverageMetricGroupFactory
-}
-
-case object LoadAverageMetricGroupFactory extends MetricGroupFactory {
-
- import LoadAverageMetrics._
-
- type GroupRecorder = LoadAverageMetricsRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.system.load-average")
-
- val oneMinuteConfig = settings.getConfig("one")
- val fiveMinutesConfig = settings.getConfig("five")
- val fifteenMinutesConfig = settings.getConfig("fifteen")
-
- new LoadAverageMetricsRecorder(
- Histogram.fromConfig(oneMinuteConfig),
- Histogram.fromConfig(fiveMinutesConfig),
- Histogram.fromConfig(fifteenMinutesConfig))
- }
-}
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala
deleted file mode 100644
index 14051427..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/MemoryMetrics.scala
+++ /dev/null
@@ -1,92 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-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: Histogram, free: Histogram, buffer: Histogram, cache: Histogram, swapUsed: Histogram, swapFree: Histogram)
- 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 = MemoryMetricGroupFactory
-}
-
-case object MemoryMetricGroupFactory extends MetricGroupFactory {
-
- import MemoryMetrics._
-
- 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(
- Histogram.fromConfig(usedConfig, Scale.Mega),
- Histogram.fromConfig(freeConfig, Scale.Mega),
- Histogram.fromConfig(swapUsedConfig, Scale.Mega),
- Histogram.fromConfig(swapFreeConfig, Scale.Mega),
- Histogram.fromConfig(bufferConfig, Scale.Mega),
- Histogram.fromConfig(cacheConfig, Scale.Mega))
- }
-} \ 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
deleted file mode 100644
index d8a38f6d..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/NetworkMetrics.scala
+++ /dev/null
@@ -1,91 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-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 object RxDropped extends MetricIdentity { val name = "rx-dropped" }
- case object TxDropped extends MetricIdentity { val name = "tx-dropped" }
-
- case class NetworkMetricRecorder(rxBytes: Histogram, txBytes: Histogram, rxErrors: Histogram, txErrors: Histogram, rxDropped: Histogram, txDropped: Histogram)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- NetworkMetricSnapshot(rxBytes.collect(context), txBytes.collect(context), rxErrors.collect(context), txErrors.collect(context), rxDropped.collect(context), txDropped.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class NetworkMetricSnapshot(rxBytes: Histogram.Snapshot, txBytes: Histogram.Snapshot, rxErrors: Histogram.Snapshot, txErrors: Histogram.Snapshot, rxDropped: Histogram.Snapshot, txDropped: 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), rxDropped.merge(that.rxDropped, context), txDropped.merge(that.txDropped, context))
- }
-
- val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- RxBytes -> rxBytes,
- TxBytes -> txBytes,
- RxErrors -> rxErrors,
- TxErrors -> txErrors,
- RxDropped -> rxDropped,
- TxDropped -> txDropped)
- }
-
- val Factory = NetworkMetricGroupFactory
-}
-
-case object NetworkMetricGroupFactory extends MetricGroupFactory {
- import NetworkMetrics._
-
- 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")
- val rxDroppedConfig = settings.getConfig("rx-dropped")
- val txDroppedConfig = settings.getConfig("tx-dropped")
-
- new NetworkMetricRecorder(
- Histogram.fromConfig(rxBytesConfig, Scale.Kilo),
- Histogram.fromConfig(txBytesConfig, Scale.Kilo),
- Histogram.fromConfig(rxErrorsConfig),
- Histogram.fromConfig(txErrorsConfig),
- Histogram.fromConfig(rxDroppedConfig),
- Histogram.fromConfig(txDroppedConfig))
- }
-} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/NonHeapMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/NonHeapMetrics.scala
deleted file mode 100644
index c2b9f9af..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/NonHeapMetrics.scala
+++ /dev/null
@@ -1,86 +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 java.lang.management.ManagementFactory
-
-import akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.{ Gauge, Histogram }
-
-case class NonHeapMetrics(name: String) extends MetricGroupIdentity {
- val category = NonHeapMetrics
-}
-
-object NonHeapMetrics extends MetricGroupCategory {
- val name = "non-heap"
-
- case object Used extends MetricIdentity { val name = "used" }
- case object Max extends MetricIdentity { val name = "max" }
- case object Committed extends MetricIdentity { val name = "committed" }
-
- case class NonHeapMetricRecorder(used: Gauge, max: Gauge, committed: Gauge)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- NonHeapMetricSnapshot(used.collect(context), max.collect(context), committed.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class NonHeapMetricSnapshot(used: Histogram.Snapshot, max: Histogram.Snapshot, committed: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = NonHeapMetricSnapshot
-
- def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
- NonHeapMetricSnapshot(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 = NonHeapMetricGroupFactory
-}
-
-case object NonHeapMetricGroupFactory extends MetricGroupFactory {
-
- import NonHeapMetrics._
- import kamon.system.SystemMetricsExtension._
-
- def nonHeap = ManagementFactory.getMemoryMXBean.getNonHeapMemoryUsage
-
- type GroupRecorder = NonHeapMetricRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.jvm.non-heap")
-
- val usedNonHeapConfig = settings.getConfig("used")
- val maxNonHeapConfig = settings.getConfig("max")
- val committedNonHeapConfig = settings.getConfig("committed")
-
- new NonHeapMetricRecorder(
- Gauge.fromConfig(usedNonHeapConfig, system, Scale.Mega)(() ⇒ toMB(nonHeap.getUsed)),
- Gauge.fromConfig(maxNonHeapConfig, system, Scale.Mega)(() ⇒ toMB(nonHeap.getMax)),
- Gauge.fromConfig(committedNonHeapConfig, system, Scale.Mega)(() ⇒ toMB(nonHeap.getCommitted)))
- }
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala
deleted file mode 100644
index ebd79d48..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/ProcessCPUMetrics.scala
+++ /dev/null
@@ -1,76 +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 akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.Histogram
-
-case class ProcessCPUMetrics(name: String) extends MetricGroupIdentity {
- val category = ProcessCPUMetrics
-}
-
-object ProcessCPUMetrics extends MetricGroupCategory {
- val name = "proc-cpu"
-
- case object CpuPercent extends MetricIdentity { val name = "cpu-percentage" }
- case object TotalProcessTime extends MetricIdentity { val name = "total-process-time" }
-
- case class ProcessCPUMetricsRecorder(cpuPercent: Histogram, totalProcessTime: Histogram)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- ProcessCPUMetricsSnapshot(cpuPercent.collect(context), totalProcessTime.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class ProcessCPUMetricsSnapshot(cpuPercent: Histogram.Snapshot, totalProcessTime: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = ProcessCPUMetricsSnapshot
-
- def merge(that: ProcessCPUMetricsSnapshot, context: CollectionContext): GroupSnapshotType = {
- ProcessCPUMetricsSnapshot(cpuPercent.merge(that.cpuPercent, context), totalProcessTime.merge(that.totalProcessTime, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- CpuPercent -> cpuPercent,
- TotalProcessTime -> totalProcessTime)
- }
-
- val Factory = ProcessCPUMetricGroupFactory
-}
-
-case object ProcessCPUMetricGroupFactory extends MetricGroupFactory {
- import ProcessCPUMetrics._
-
- type GroupRecorder = ProcessCPUMetricsRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.system.process-cpu")
-
- val cpuPercentageConfig = settings.getConfig("cpu-percentage")
- val totalProcessTimeConfig = settings.getConfig("total-process-time")
-
- new ProcessCPUMetricsRecorder(
- Histogram.fromConfig(cpuPercentageConfig),
- Histogram.fromConfig(totalProcessTimeConfig))
- }
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/metrics/ThreadMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/metrics/ThreadMetrics.scala
deleted file mode 100644
index fc039ffa..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/metrics/ThreadMetrics.scala
+++ /dev/null
@@ -1,85 +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 java.lang.management.ManagementFactory
-
-import akka.actor.ActorSystem
-import com.typesafe.config.Config
-import kamon.metric._
-import kamon.metric.instrument.{ Gauge, Histogram }
-
-case class ThreadMetrics(name: String) extends MetricGroupIdentity {
- val category = ThreadMetrics
-}
-
-object ThreadMetrics extends MetricGroupCategory {
- val name = "thread"
-
- case object Damon extends MetricIdentity { val name = "daemon-count" }
- case object Count extends MetricIdentity { val name = "count" }
- case object Peak extends MetricIdentity { val name = "peak-count" }
-
- case class ThreadMetricRecorder(daemon: Gauge, count: Gauge, peak: Gauge)
- extends MetricGroupRecorder {
-
- def collect(context: CollectionContext): MetricGroupSnapshot = {
- ThreadMetricSnapshot(daemon.collect(context), count.collect(context), peak.collect(context))
- }
-
- def cleanup: Unit = {}
- }
-
- case class ThreadMetricSnapshot(daemon: Histogram.Snapshot, count: Histogram.Snapshot, peak: Histogram.Snapshot)
- extends MetricGroupSnapshot {
-
- type GroupSnapshotType = ThreadMetricSnapshot
-
- def merge(that: GroupSnapshotType, context: CollectionContext): GroupSnapshotType = {
- ThreadMetricSnapshot(daemon.merge(that.daemon, context), count.merge(that.count, context), peak.merge(that.peak, context))
- }
-
- lazy val metrics: Map[MetricIdentity, MetricSnapshot] = Map(
- Damon -> daemon,
- Count -> count,
- Peak -> peak)
- }
-
- val Factory = ThreadMetricGroupFactory
-}
-
-case object ThreadMetricGroupFactory extends MetricGroupFactory {
-
- import ThreadMetrics._
-
- def threads = ManagementFactory.getThreadMXBean
-
- type GroupRecorder = ThreadMetricRecorder
-
- def create(config: Config, system: ActorSystem): GroupRecorder = {
- val settings = config.getConfig("precision.jvm.thread")
-
- val daemonThreadConfig = settings.getConfig("daemon")
- val countThreadsConfig = settings.getConfig("count")
- val peakThreadsConfig = settings.getConfig("peak")
-
- new ThreadMetricRecorder(
- Gauge.fromConfig(daemonThreadConfig, system)(() ⇒ threads.getDaemonThreadCount.toLong),
- Gauge.fromConfig(countThreadsConfig, system)(() ⇒ threads.getThreadCount.toLong),
- Gauge.fromConfig(peakThreadsConfig, system)(() ⇒ threads.getPeakThreadCount.toLong))
- }
-}
-
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/GcMetricsCollector.scala b/kamon-system-metrics/src/main/scala/kamon/system/GcMetricsCollector.scala
deleted file mode 100644
index ae2f50cf..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/system/GcMetricsCollector.scala
+++ /dev/null
@@ -1,77 +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 java.lang.management.GarbageCollectorMXBean
-
-import akka.actor.{ Actor, Props }
-import kamon.metrics.GCMetrics.GCMetricRecorder
-
-import scala.concurrent.duration.FiniteDuration
-
-class GcMetricsCollector(collectInterval: FiniteDuration, recorder: Option[GCMetricRecorder], extractor: GcMetricExtractor) extends Actor {
- import kamon.system.GcMetricsCollector._
-
- val collectSchedule = context.system.scheduler.schedule(collectInterval, collectInterval, self, Collect)(SystemMetrics(context.system).dispatcher)
-
- def receive: Receive = {
- case Collect ⇒ collectMetrics()
- }
-
- override def postStop() = collectSchedule.cancel()
-
- def collectMetrics(): Unit = recorder.map(recordGc)
-
- private def recordGc(gcr: GCMetricRecorder) = {
- val gcMeasure = extractor.extract()
-
- gcr.count.record(gcMeasure.collectionCount)
- gcr.time.record(gcMeasure.collectionTime)
- }
-}
-
-object GcMetricsCollector {
- case object Collect
-
- def props(collectInterval: FiniteDuration, recorder: Option[GCMetricRecorder], extractor: GcMetricExtractor): Props = Props(classOf[GcMetricsCollector], collectInterval, recorder, extractor)
-}
-
-case class GcMeasure(collectionCount: Long, collectionTime: Long)
-
-case class GcMetricExtractor(gc: GarbageCollectorMXBean) {
- var previousGcCount = 0L
- var previousGcTime = 0L
-
- def extract(): GcMeasure = {
- var diffCollectionCount = 0L
- var diffCollectionTime = 0L
-
- val collectionCount = gc.getCollectionCount
- val collectionTime = gc.getCollectionTime
-
- if (collectionCount > 0)
- diffCollectionCount = collectionCount - previousGcCount
-
- if (collectionTime > 0)
- diffCollectionTime = collectionTime - previousGcTime
-
- previousGcCount = collectionCount
- previousGcTime = collectionTime
-
- GcMeasure(diffCollectionCount, diffCollectionTime)
- }
-} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala
deleted file mode 100644
index cb3e2695..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetrics.scala
+++ /dev/null
@@ -1,78 +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 java.lang.management.ManagementFactory
-import akka.actor._
-import akka.event.Logging
-import kamon.Kamon
-import kamon.metric.Metrics
-import kamon.metrics._
-import scala.collection.JavaConverters._
-import scala.concurrent.duration._
-
-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 config = system.settings.config.getConfig("kamon.system-metrics")
- val dispatcher = system.dispatchers.lookup(config.getString("dispatcher"))
- val sigarFolder = system.settings.config.getString("kamon.sigar.folder")
- val systemMetricsExtension = Kamon(Metrics)(system)
-
- //System Metrics
- system.actorOf(SystemMetricsCollector.props(1 second), "system-metrics-collector")
-
- //JVM Metrics
- systemMetricsExtension.register(HeapMetrics(Heap), HeapMetrics.Factory)
- systemMetricsExtension.register(NonHeapMetrics(NonHeap), NonHeapMetrics.Factory)
- systemMetricsExtension.register(ClassLoadingMetrics(Classes), ClassLoadingMetrics.Factory)
- systemMetricsExtension.register(ThreadMetrics(Threads), ThreadMetrics.Factory)
-
- garbageCollectors.map { gc ⇒
- val gcName = sanitize(gc.getName)
- val recorder = systemMetricsExtension.register(GCMetrics(gcName), GCMetrics.Factory(gc))
- system.actorOf(GcMetricsCollector.props(1 second, recorder, GcMetricExtractor(gc)), s"$gcName-collector")
- }
-}
-
-object SystemMetricsExtension {
- val CPU = "cpu"
- val ProcessCPU = "process-cpu"
- val Network = "network"
- val Memory = "memory"
- val Heap = "heap"
- val NonHeap = "non-heap"
- val Classes = "classes"
- val Threads = "thread"
- val ContextSwitches = "context-switches"
- val Disk = "disk"
- val LoadAverage = "load-average"
-
- def toKB(value: Long): Long = value / 1024
- def toMB(value: Long): Long = value / 1024 / 1024
- def toLong(value: Double): Long = math round (value * 100L)
- def sanitize(str: String): String = str.replaceAll("""[^\w]""", "-")
-
- val garbageCollectors = ManagementFactory.getGarbageCollectorMXBeans.asScala.filter(_.isValid)
-}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsBanner.scala b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsBanner.scala
deleted file mode 100644
index 99e09da9..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsBanner.scala
+++ /dev/null
@@ -1,91 +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.ActorLogging
-import org.hyperic.sigar._
-
-import scala.util.control.NoStackTrace
-
-trait SystemMetricsBanner {
- self: ActorLogging ⇒
-
- def printBanner(sigar: Sigar) = {
- val os = OperatingSystem.getInstance
-
- def loadAverage(sigar: Sigar) = try {
- val average = sigar.getLoadAverage
- (average(0), average(1), average(2))
- } catch {
- case s: org.hyperic.sigar.SigarNotImplementedException ⇒ (0d, 0d, 0d)
- }
-
- def uptime(sigar: Sigar) = {
- def formatUptime(uptime: Double): String = {
- var retval: String = ""
- val days: Int = uptime.toInt / (60 * 60 * 24)
- var minutes: Int = 0
- var hours: Int = 0
-
- if (days != 0) {
- retval += s"$days ${if (days > 1) "days" else "day"}, "
- }
-
- minutes = uptime.toInt / 60
- hours = minutes / 60
- hours %= 24
- minutes %= 60
-
- if (hours != 0) {
- retval += hours + ":" + minutes
- } else {
- retval += minutes + " min"
- }
- retval
- }
-
- val uptime = sigar.getUptime
- val now = System.currentTimeMillis()
-
- s"up ${formatUptime(uptime.getUptime)}"
- }
-
- val message =
- """
- |
- | _____ _ __ __ _ _ _ _ _
- | / ____| | | | \/ | | | (_) | | | | | |
- || (___ _ _ ___| |_ ___ _ __ ___ | \ / | ___| |_ _ __ _ ___ ___| | ___ __ _ __| | ___ __| |
- | \___ \| | | / __| __/ _ \ '_ ` _ \| |\/| |/ _ \ __| '__| |/ __/ __| | / _ \ / _` |/ _` |/ _ \/ _` |
- | ____) | |_| \__ \ || __/ | | | | | | | | __/ |_| | | | (__\__ \ |___| (_) | (_| | (_| | __/ (_| |
- ||_____/ \__, |___/\__\___|_| |_| |_|_| |_|\___|\__|_| |_|\___|___/______\___/ \__,_|\__,_|\___|\__,_|
- | __/ |
- | |___/
- |
- | [System Status] [OS Information]
- | |--------------------------------| |----------------------------------------|
- | Up Time: %-10s Description: %s
- | Load Average: %-16s Name: %s
- | Version: %s
- | Arch: %s
- |
- """.stripMargin.format(uptime(sigar), os.getDescription, loadAverage(sigar), os.getName, os.getVersion, os.getArch)
- log.info(message)
- }
-
- class UnexpectedSigarException(message: String) extends RuntimeException(message) with NoStackTrace
-}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsCollector.scala b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsCollector.scala
deleted file mode 100644
index 4391240a..00000000
--- a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsCollector.scala
+++ /dev/null
@@ -1,266 +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 java.io.{ File, IOException }
-
-import akka.actor.{ Actor, ActorLogging, Props }
-import kamon.Kamon
-import kamon.metric.Metrics
-import kamon.metrics.CPUMetrics.CPUMetricRecorder
-import kamon.metrics.ContextSwitchesMetrics.ContextSwitchesMetricsRecorder
-import kamon.metrics.DiskMetrics.DiskMetricsRecorder
-import kamon.metrics.LoadAverageMetrics.LoadAverageMetricsRecorder
-import kamon.metrics.MemoryMetrics.MemoryMetricRecorder
-import kamon.metrics.NetworkMetrics.NetworkMetricRecorder
-import kamon.metrics.ProcessCPUMetrics.ProcessCPUMetricsRecorder
-import kamon.metrics._
-import kamon.sigar.SigarProvisioner
-import org.hyperic.sigar._
-
-import scala.collection.concurrent.TrieMap
-import scala.concurrent.duration.FiniteDuration
-import scala.io.Source
-import scala.collection.mutable
-
-class SystemMetricsCollector(collectInterval: FiniteDuration) extends Actor with ActorLogging with SystemMetricsBanner {
- import kamon.system.SystemMetricsCollector._
- import kamon.system.SystemMetricsExtension._
-
- lazy val sigar = createSigarInstance
- def pid = sigar.getPid
-
- val interfaces = sigar.getNetInterfaceList.filterNot(NetworkFilter).toSet
- val fileSystems = sigar.getFileSystemList.filter(_.getType == FileSystem.TYPE_LOCAL_DISK).map(_.getDevName).toSet
-
- val metricExtension = Kamon(Metrics)(context.system)
- val collectSchedule = context.system.scheduler.schedule(collectInterval, collectInterval, self, Collect)(SystemMetrics(context.system).dispatcher)
-
- val cpuRecorder = metricExtension.register(CPUMetrics(CPU), CPUMetrics.Factory)
- val processCpuRecorder = metricExtension.register(ProcessCPUMetrics(ProcessCPU), ProcessCPUMetrics.Factory)
- val memoryRecorder = metricExtension.register(MemoryMetrics(Memory), MemoryMetrics.Factory)
- val networkRecorder = metricExtension.register(NetworkMetrics(Network), NetworkMetrics.Factory)
- val contextSwitchesRecorder = metricExtension.register(ContextSwitchesMetrics(ContextSwitches), ContextSwitchesMetrics.Factory)
- val diskRecorder = metricExtension.register(DiskMetrics(Disk), DiskMetrics.Factory)
- val loadAverageRecorder = metricExtension.register(LoadAverageMetrics(LoadAverage), LoadAverageMetrics.Factory)
-
- def receive: Receive = {
- case Collect ⇒ collectMetrics()
- }
-
- override def postStop() = collectSchedule.cancel()
-
- def collectMetrics() = {
- cpuRecorder.map(recordCpu)
- processCpuRecorder.map(recordProcessCpu)
- memoryRecorder.map(recordMemory)
- networkRecorder.map(recordNetwork)
- diskRecorder.map(recordDisk)
- loadAverageRecorder.map(recordLoadAverage)
-
- if (OsUtils.isLinux)
- contextSwitchesRecorder.map(recordContextSwitches)
- }
-
- private def recordCpu(cpur: CPUMetricRecorder) = {
- val cpuPerc = sigar.getCpuPerc
- cpur.user.record(toLong(cpuPerc.getUser))
- cpur.system.record(toLong(cpuPerc.getSys))
- cpur.cpuWait.record(toLong(cpuPerc.getWait))
- cpur.idle.record(toLong(cpuPerc.getIdle))
- cpur.stolen.record(toLong(cpuPerc.getStolen))
- }
-
- private def recordProcessCpu(pcpur: ProcessCPUMetricsRecorder) = {
- val procCpu = sigar.getProcCpu(pid)
- val procTime = sigar.getProcTime(pid)
-
- pcpur.cpuPercent.record(toLong(procCpu.getPercent))
- pcpur.totalProcessTime.record(procTime.getTotal) // gives an idea of what is really measured and then interpreted as %
- }
-
- private def recordMemory(mr: MemoryMetricRecorder) = {
- val mem = sigar.getMem
- val swap = sigar.getSwap
-
- mr.used.record(toMB(mem.getUsed))
- mr.free.record(toMB(mem.getFree))
- mr.swapUsed.record(toMB(swap.getUsed))
- mr.swapFree.record(toMB(swap.getFree))
- mr.buffer.record(toMB(collectBuffer(mem)))
- mr.cache.record(toMB(collectCache(mem)))
-
- def collectBuffer(mem: Mem): Long = if (mem.getUsed != mem.getActualUsed) mem.getActualUsed else 0L
- def collectCache(mem: Mem): Long = if (mem.getFree != mem.getActualFree) mem.getActualFree else 0L
- }
-
- private def recordNetwork(nr: NetworkMetricRecorder) = {
- import Networks._
- nr.rxBytes.record(collect(sigar, interfaces, RxBytes, previousNetworkMetrics)(net ⇒ toKB(net.getRxBytes)))
- nr.txBytes.record(collect(sigar, interfaces, TxBytes, previousNetworkMetrics)(net ⇒ toKB(net.getTxBytes)))
- nr.rxErrors.record(collect(sigar, interfaces, RxErrors, previousNetworkMetrics)(net ⇒ net.getRxErrors))
- nr.txErrors.record(collect(sigar, interfaces, TxErrors, previousNetworkMetrics)(net ⇒ net.getTxErrors))
- nr.rxDropped.record(collect(sigar, interfaces, RxDropped, previousNetworkMetrics)(net ⇒ net.getRxDropped))
- nr.txDropped.record(collect(sigar, interfaces, TxDropped, previousNetworkMetrics)(net ⇒ net.getTxDropped))
-
- def collect(sigar: SigarProxy, interfaces: Set[String], name: String, previousMetrics: TrieMap[String, mutable.Map[String, Long]])(thunk: NetInterfaceStat ⇒ Long): Long = {
- interfaces.foldLeft(0L) { (acc, interface) ⇒
- {
- val net = sigar.getNetInterfaceStat(interface)
- val previous = previousMetrics.getOrElse(interface, mutable.Map.empty[String, Long])
- val current = thunk(net)
- val delta = current - previous.getOrElse(name, 0L)
- previousMetrics.put(interface, previous += name -> current)
- acc + delta
- }
- }
- }
- }
-
- private def recordDisk(rd: DiskMetricsRecorder) = {
- import Disks._
-
- rd.reads.record(collect(sigar, fileSystems, Reads, previousDiskMetrics)(disk ⇒ disk.getReads))
- rd.writes.record(collect(sigar, fileSystems, Writes, previousDiskMetrics)(disk ⇒ disk.getWrites))
- rd.queue.record(collect(sigar, fileSystems, Queue, previousDiskMetrics)(disk ⇒ toLong(disk.getQueue)))
- rd.serviceTime.record(collect(sigar, fileSystems, Service, previousDiskMetrics)(disk ⇒ toLong(disk.getServiceTime)))
- }
-
- def collect(sigar: SigarProxy, fileSystems: Set[String], name: String, previousMetrics: TrieMap[String, mutable.Map[String, Long]])(thunk: DiskUsage ⇒ Long): Long = {
- fileSystems.foldLeft(0L) { (acc, fileSystem) ⇒
- {
- val disk = sigar.getDiskUsage(fileSystem)
- val previous = previousMetrics.getOrElse(fileSystem, mutable.Map.empty[String, Long])
- val value = thunk(disk)
- val current = if (value == Sigar.FIELD_NOTIMPL) 0L else value
- val delta = current - previous.getOrElse(name, 0L)
- previousMetrics.put(fileSystem, previous += name -> current)
- acc + delta
- }
- }
- }
-
- private def recordLoadAverage(lar: LoadAverageMetricsRecorder) = {
- val loadAverage = sigar.getLoadAverage
- val (one, five, fifteen) = (loadAverage(0), loadAverage(1), loadAverage(2))
-
- lar.one.record(toLong(one))
- lar.five.record(toLong(five))
- lar.fifteen.record(toLong(fifteen))
- }
-
- private def recordContextSwitches(rcs: ContextSwitchesMetricsRecorder) = {
- def contextSwitchesByProcess(pid: Long): (Long, Long) = {
- val filename = s"/proc/$pid/status"
- var voluntaryContextSwitches = 0L
- var nonVoluntaryContextSwitches = 0L
-
- try {
- for (line ← Source.fromFile(filename).getLines()) {
- if (line.startsWith("voluntary_ctxt_switches")) {
- voluntaryContextSwitches = line.substring(line.indexOf(":") + 1).trim.toLong
- }
- if (line.startsWith("nonvoluntary_ctxt_switches")) {
- nonVoluntaryContextSwitches = line.substring(line.indexOf(":") + 1).trim.toLong
- }
- }
- } catch {
- case ex: IOException ⇒ log.error("Error trying to read [{}]", filename)
- }
- (voluntaryContextSwitches, nonVoluntaryContextSwitches)
- }
-
- def contextSwitches: Long = {
- val filename = "/proc/stat"
- var contextSwitches = 0L
-
- try {
- for (line ← Source.fromFile(filename).getLines()) {
- if (line.startsWith("rcs")) {
- contextSwitches = line.substring(line.indexOf(" ") + 1).toLong
- }
- }
- } catch {
- case ex: IOException ⇒ log.error("Error trying to read [{}]", filename)
- }
- contextSwitches
- }
-
- val (perProcessVoluntary, perProcessNonVoluntary) = contextSwitchesByProcess(pid)
- rcs.perProcessVoluntary.record(perProcessVoluntary)
- rcs.perProcessNonVoluntary.record(perProcessNonVoluntary)
- rcs.global.record(contextSwitches)
- }
-
- def verifiedSigarInstance: SigarProxy = {
- val sigar = new Sigar()
- printBanner(sigar)
- sigar
- }
-
- def provisionSigarLibrary: Unit = {
- val folder = SystemMetrics(context.system).sigarFolder
- SigarProvisioner.provision(new File(folder))
- }
-
- def createSigarInstance: SigarProxy = {
- // 1) Assume that library is already provisioned.
- try {
- return verifiedSigarInstance
- } catch {
- // Not using [[Try]] - any error is non-fatal in this case.
- case e: Throwable ⇒ log.info(s"Sigar is not yet provisioned: ${e}")
- }
-
- // 2) Attempt to provision library via sigar-loader.
- try {
- provisionSigarLibrary
- return verifiedSigarInstance
- } catch {
- // Not using [[Try]] - any error is non-fatal in this case.
- case e: Throwable ⇒ throw new UnexpectedSigarException(s"Failed to load Sigar: ${e}")
- }
- }
-}
-
-object SystemMetricsCollector {
- val NetworkFilter = Set("lo")
- val previousDiskMetrics = TrieMap[String, mutable.Map[String, Long]]()
- val previousNetworkMetrics = TrieMap[String, mutable.Map[String, Long]]()
-
- object Networks {
- val RxBytes = "rxBytes"
- val TxBytes = "txBytes"
- val RxErrors = "rxErrors"
- val TxErrors = "txErrors"
- val RxDropped = "rxDropped"
- val TxDropped = "txDropped"
- }
-
- object Disks {
- val Reads = "reads"
- val Writes = "writes"
- val Queue = "queue"
- val Service = "service"
- }
- case object Collect
-
- object OsUtils {
- def isLinux: Boolean = System.getProperty("os.name").indexOf("Linux") != -1
- }
-
- def props(collectInterval: FiniteDuration): Props = Props(classOf[SystemMetricsCollector], collectInterval)
-} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsExtension.scala b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsExtension.scala
new file mode 100644
index 00000000..df120611
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/SystemMetricsExtension.scala
@@ -0,0 +1,70 @@
+/*
+ * =========================================================================================
+ * 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.io.File
+import akka.actor._
+import akka.event.Logging
+import kamon.system.custom.{ ContextSwitchesUpdater, ContextSwitchesMetrics }
+import kamon.system.jmx._
+import kamon.{ ModuleSupervisor, Kamon }
+import kamon.metric._
+import kamon.sigar.SigarProvisioner
+import kamon.system.sigar.SigarMetricsUpdater
+
+import kamon.util.ConfigTools.Syntax
+
+object SystemMetrics extends ExtensionId[SystemMetricsExtension] with ExtensionIdProvider {
+ override def lookup(): ExtensionId[_ <: Extension] = SystemMetrics
+ override def createExtension(system: ExtendedActorSystem): SystemMetricsExtension = new SystemMetricsExtension(system)
+}
+
+class SystemMetricsExtension(system: ExtendedActorSystem) extends Kamon.Extension {
+
+ val log = Logging(system, classOf[SystemMetricsExtension])
+ log.info(s"Starting the Kamon(SystemMetrics) extension")
+
+ val config = system.settings.config.getConfig("kamon.system-metrics")
+ val sigarFolder = config.getString("sigar-native-folder")
+ val sigarRefreshInterval = config.getFiniteDuration("sigar-metrics-refresh-interval")
+ val contextSwitchesRefreshInterval = config.getFiniteDuration("context-switches-refresh-interval")
+ val metricsExtension = Kamon(Metrics)(system)
+
+ // Sigar-based metrics
+ SigarProvisioner.provision(new File(sigarFolder))
+ val sigarMetricsRecorder = ModuleSupervisor.get(system).createModule("sigar-metrics-recorder",
+ SigarMetricsUpdater.props(sigarRefreshInterval).withDispatcher("kamon.system-metrics.sigar-dispatcher"))
+
+ // JMX Metrics
+ ClassLoadingMetrics.register(metricsExtension)
+ GarbageCollectionMetrics.register(metricsExtension)
+ HeapMemoryMetrics.register(metricsExtension)
+ NonHeapMemoryMetrics.register(metricsExtension)
+ ThreadsMetrics.register(metricsExtension)
+
+ // If we are in Linux, add ContextSwitchesMetrics as well.
+ if (isLinux) {
+ val contextSwitchesRecorder = ContextSwitchesMetrics.register(system, contextSwitchesRefreshInterval)
+
+ ModuleSupervisor.get(system).createModule("context-switches-metrics-recorder",
+ ContextSwitchesUpdater.props(contextSwitchesRecorder, sigarRefreshInterval)
+ .withDispatcher("kamon.system-metrics.context-switches-dispatcher"))
+ }
+
+ def isLinux: Boolean =
+ System.getProperty("os.name").indexOf("Linux") != -1
+
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/custom/ContextSwitchesMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/custom/ContextSwitchesMetrics.scala
new file mode 100644
index 00000000..a3c56733
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/custom/ContextSwitchesMetrics.scala
@@ -0,0 +1,96 @@
+package kamon.system.custom
+
+import java.io.IOException
+import java.nio.charset.StandardCharsets
+import java.nio.file.{ Paths, Files }
+
+import akka.actor.{ Props, Actor, ActorSystem }
+import akka.event.{ Logging, LoggingAdapter }
+import kamon.Kamon
+import kamon.metric._
+import kamon.metric.instrument.InstrumentFactory
+import kamon.system.custom.ContextSwitchesUpdater.UpdateContextSwitches
+import org.hyperic.sigar.Sigar
+import scala.collection.JavaConverters.iterableAsScalaIterableConverter
+import scala.concurrent.duration.FiniteDuration
+
+class ContextSwitchesMetrics(pid: Long, log: LoggingAdapter, instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) {
+ val perProcessVoluntary = histogram("context-switches-process-voluntary")
+ val perProcessNonVoluntary = histogram("context-switches-process-non-voluntary")
+ val global = histogram("context-switches-global")
+
+ def update(): Unit = {
+ def contextSwitchesByProcess(pid: Long): (Long, Long) = {
+ val filename = s"/proc/$pid/status"
+ var voluntaryContextSwitches = 0L
+ var nonVoluntaryContextSwitches = 0L
+
+ try {
+ for (line ← Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII).asScala.toList) {
+ if (line.startsWith("voluntary_ctxt_switches")) {
+ voluntaryContextSwitches = line.substring(line.indexOf(":") + 1).trim.toLong
+ }
+ if (line.startsWith("nonvoluntary_ctxt_switches")) {
+ nonVoluntaryContextSwitches = line.substring(line.indexOf(":") + 1).trim.toLong
+ }
+ }
+ } catch {
+ case ex: IOException ⇒ log.error("Error trying to read [{}]", filename)
+ }
+ (voluntaryContextSwitches, nonVoluntaryContextSwitches)
+ }
+
+ def contextSwitches: Long = {
+ val filename = "/proc/stat"
+ var contextSwitches = 0L
+
+ try {
+ for (line ← Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII).asScala.toList) {
+ if (line.startsWith("rcs")) {
+ contextSwitches = line.substring(line.indexOf(" ") + 1).toLong
+ }
+ }
+ } catch {
+ case ex: IOException ⇒ log.error("Error trying to read [{}]", filename)
+ }
+ contextSwitches
+ }
+
+ val (voluntary, nonVoluntary) = contextSwitchesByProcess(pid)
+ perProcessVoluntary.record(voluntary)
+ perProcessNonVoluntary.record(nonVoluntary)
+ global.record(contextSwitches)
+ }
+}
+
+object ContextSwitchesMetrics {
+
+ def register(system: ActorSystem, refreshInterval: FiniteDuration): ContextSwitchesMetrics = {
+ val metricsExtension = Kamon(Metrics)(system)
+ val log = Logging(system, "ContextSwitchesMetrics")
+ val pid = (new Sigar).getPid
+
+ val instrumentFactory = metricsExtension.instrumentFactory("system-metric")
+ metricsExtension.register(Entity("context-switches", "system-metric"), new ContextSwitchesMetrics(pid, log, instrumentFactory)).recorder
+ }
+}
+
+class ContextSwitchesUpdater(csm: ContextSwitchesMetrics, refreshInterval: FiniteDuration) extends Actor {
+ val schedule = context.system.scheduler.schedule(refreshInterval, refreshInterval, self, UpdateContextSwitches)(context.dispatcher)
+
+ def receive = {
+ case UpdateContextSwitches ⇒ csm.update()
+ }
+
+ override def postStop(): Unit = {
+ schedule.cancel()
+ super.postStop()
+ }
+}
+
+object ContextSwitchesUpdater {
+ case object UpdateContextSwitches
+
+ def props(csm: ContextSwitchesMetrics, refreshInterval: FiniteDuration): Props =
+ Props(new ContextSwitchesUpdater(csm, refreshInterval))
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/ClassLoadingMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/ClassLoadingMetrics.scala
new file mode 100644
index 00000000..d9379738
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/ClassLoadingMetrics.scala
@@ -0,0 +1,28 @@
+package kamon.system.jmx
+
+import java.lang.management.ManagementFactory
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.{ Memory, InstrumentFactory }
+
+class ClassLoadingMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) {
+ val classLoadingBean = ManagementFactory.getClassLoadingMXBean
+
+ gauge("classes-loaded", Memory.Bytes, () ⇒ {
+ classLoadingBean.getTotalLoadedClassCount
+ })
+
+ gauge("classes-unloaded", Memory.Bytes, () ⇒ {
+ classLoadingBean.getUnloadedClassCount
+ })
+
+ gauge("classes-currently-loaded", Memory.Bytes, () ⇒ {
+ classLoadingBean.getLoadedClassCount.toLong
+ })
+
+}
+
+object ClassLoadingMetrics extends JmxSystemMetricRecorderCompanion("class-loading") {
+ def apply(instrumentFactory: InstrumentFactory): ClassLoadingMetrics =
+ new ClassLoadingMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala
new file mode 100644
index 00000000..b7d2fe6a
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala
@@ -0,0 +1,34 @@
+package kamon.system.jmx
+
+import java.lang.management.{ GarbageCollectorMXBean, ManagementFactory }
+
+import kamon.metric.{ Entity, MetricsExtension, GenericEntityRecorder }
+import kamon.metric.instrument.{ DifferentialValueCollector, Time, InstrumentFactory }
+import scala.collection.JavaConverters._
+
+class GarbageCollectionMetrics(gc: GarbageCollectorMXBean, instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) {
+
+ gauge("garbage-collection-count", DifferentialValueCollector(() ⇒ {
+ gc.getCollectionCount
+ }))
+
+ gauge("garbage-collection-time", Time.Milliseconds, DifferentialValueCollector(() ⇒ {
+ gc.getCollectionTime
+ }))
+
+}
+
+object GarbageCollectionMetrics {
+
+ def sanitizeCollectorName(name: String): String =
+ name.replaceAll("""[^\w]""", "-").toLowerCase
+
+ def register(metricsExtension: MetricsExtension): Unit = {
+
+ val instrumentFactory = metricsExtension.instrumentFactory("system-metric")
+ ManagementFactory.getGarbageCollectorMXBeans.asScala.filter(_.isValid) map { gc ⇒
+ val gcName = sanitizeCollectorName(gc.getName)
+ metricsExtension.register(Entity(s"$gcName-garbage-collector", "system-metric"), new GarbageCollectionMetrics(gc, instrumentFactory))
+ }
+ }
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/HeapMemoryMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/HeapMemoryMetrics.scala
new file mode 100644
index 00000000..a96b5319
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/HeapMemoryMetrics.scala
@@ -0,0 +1,29 @@
+package kamon.system.jmx
+
+import java.lang.management.ManagementFactory
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.{ Memory, InstrumentFactory }
+
+class HeapMemoryMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) {
+ val memoryBean = ManagementFactory.getMemoryMXBean
+ def nonHeapUsage = memoryBean.getHeapMemoryUsage
+
+ gauge("heap-used", Memory.Bytes, () ⇒ {
+ nonHeapUsage.getUsed
+ })
+
+ gauge("heap-max", Memory.Bytes, () ⇒ {
+ nonHeapUsage.getMax
+ })
+
+ gauge("heap-committed", Memory.Bytes, () ⇒ {
+ nonHeapUsage.getCommitted
+ })
+
+}
+
+object HeapMemoryMetrics extends JmxSystemMetricRecorderCompanion("heap-memory") {
+ def apply(instrumentFactory: InstrumentFactory): HeapMemoryMetrics =
+ new HeapMemoryMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala
new file mode 100644
index 00000000..d19622e6
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala
@@ -0,0 +1,13 @@
+package kamon.system.jmx
+
+import kamon.metric.instrument.InstrumentFactory
+import kamon.metric.{ Entity, EntityRecorder, MetricsExtension }
+
+abstract class JmxSystemMetricRecorderCompanion(metricName: String) {
+ def register(metricsExtension: MetricsExtension): EntityRecorder = {
+ val instrumentFactory = metricsExtension.instrumentFactory("system-metric")
+ metricsExtension.register(Entity(metricName, "system-metric"), apply(instrumentFactory)).recorder
+ }
+
+ def apply(instrumentFactory: InstrumentFactory): EntityRecorder
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/NonHeapMemoryMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/NonHeapMemoryMetrics.scala
new file mode 100644
index 00000000..34a23d4f
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/NonHeapMemoryMetrics.scala
@@ -0,0 +1,33 @@
+package kamon.system.jmx
+
+import java.lang.management.ManagementFactory
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.{ Memory, InstrumentFactory }
+
+class NonHeapMemoryMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) {
+ val memoryBean = ManagementFactory.getMemoryMXBean
+ def nonHeapUsage = memoryBean.getNonHeapMemoryUsage
+
+ gauge("non-heap-used", Memory.Bytes, () ⇒ {
+ nonHeapUsage.getUsed
+ })
+
+ gauge("non-heap-max", Memory.Bytes, () ⇒ {
+ val max = nonHeapUsage.getMax
+
+ // .getMax can return -1 if the max is not defined.
+ if (max >= 0) max
+ else 0
+ })
+
+ gauge("non-heap-committed", Memory.Bytes, () ⇒ {
+ nonHeapUsage.getCommitted
+ })
+
+}
+
+object NonHeapMemoryMetrics extends JmxSystemMetricRecorderCompanion("non-heap-memory") {
+ def apply(instrumentFactory: InstrumentFactory): NonHeapMemoryMetrics =
+ new NonHeapMemoryMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/ThreadsMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/ThreadsMetrics.scala
new file mode 100644
index 00000000..b33eb3e6
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/ThreadsMetrics.scala
@@ -0,0 +1,28 @@
+package kamon.system.jmx
+
+import java.lang.management.ManagementFactory
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.InstrumentFactory
+
+class ThreadsMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) {
+ val threadsBean = ManagementFactory.getThreadMXBean
+
+ gauge("daemon-thread-count", () ⇒ {
+ threadsBean.getDaemonThreadCount.toLong
+ })
+
+ gauge("peak-thread-count", () ⇒ {
+ threadsBean.getPeakThreadCount.toLong
+ })
+
+ gauge("thread-count", () ⇒ {
+ threadsBean.getThreadCount.toLong
+ })
+
+}
+
+object ThreadsMetrics extends JmxSystemMetricRecorderCompanion("threads") {
+ def apply(instrumentFactory: InstrumentFactory): ThreadsMetrics =
+ new ThreadsMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/CpuMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/CpuMetrics.scala
new file mode 100644
index 00000000..0a5f6494
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/CpuMetrics.scala
@@ -0,0 +1,29 @@
+package kamon.system.sigar
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.InstrumentFactory
+import org.hyperic.sigar.Sigar
+
+class CpuMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) with SigarMetric {
+ val user = histogram("cpu-user")
+ val system = histogram("cpu-system")
+ val Wait = histogram("cpu-wait")
+ val idle = histogram("cpu-idle")
+ val stolen = histogram("cpu-stolen")
+
+ def update(sigar: Sigar): Unit = {
+ val cpuPerc = sigar.getCpuPerc
+
+ user.record((cpuPerc.getUser * 100L).toLong)
+ system.record((cpuPerc.getSys * 100L).toLong)
+ Wait.record((cpuPerc.getWait * 100L).toLong)
+ idle.record((cpuPerc.getIdle * 100L).toLong)
+ stolen.record((cpuPerc.getStolen * 100L).toLong)
+ }
+}
+
+object CpuMetrics extends SigarMetricRecorderCompanion("cpu") {
+
+ def apply(instrumentFactory: InstrumentFactory): CpuMetrics =
+ new CpuMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/DiffRecordingHistogram.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/DiffRecordingHistogram.scala
new file mode 100644
index 00000000..94aa76d1
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/DiffRecordingHistogram.scala
@@ -0,0 +1,41 @@
+package kamon.system.sigar
+
+import java.util.concurrent.atomic.AtomicLong
+
+import kamon.metric.instrument.{ CollectionContext, Histogram }
+
+/**
+ * Wrapper Histogram for cases in which the recorded values should always be the difference
+ * between the current value and the last recorded value. This is not thread-safe and only
+ * to be used with Sigar-based metrics that are securely updated within an actor.
+ */
+class DiffRecordingHistogram(wrappedHistogram: Histogram) extends Histogram {
+ @volatile private var _recordedAtLeastOnce = false
+ private val _lastObservedValue = new AtomicLong(0)
+
+ private def processRecording(value: Long, count: Long): Unit = {
+ if (_recordedAtLeastOnce)
+ wrappedHistogram.record(value - _lastObservedValue.getAndSet(value), count)
+ else {
+ _lastObservedValue.set(value)
+ _recordedAtLeastOnce = true
+ }
+ }
+
+ def record(value: Long): Unit =
+ processRecording(value, 1)
+
+ def record(value: Long, count: Long): Unit =
+ processRecording(value, count)
+
+ def cleanup: Unit =
+ wrappedHistogram.cleanup
+
+ def collect(context: CollectionContext): Histogram.Snapshot =
+ wrappedHistogram.collect(context)
+}
+
+object DiffRecordingHistogram {
+ def apply(histogram: Histogram): DiffRecordingHistogram =
+ new DiffRecordingHistogram(histogram)
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/FileSystemMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/FileSystemMetrics.scala
new file mode 100644
index 00000000..dffebf5a
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/FileSystemMetrics.scala
@@ -0,0 +1,25 @@
+package kamon.system.sigar
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.{ Memory, InstrumentFactory }
+import org.hyperic.sigar.{ DiskUsage, FileSystem, Sigar }
+
+class FileSystemMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) with SigarMetric {
+ val reads = DiffRecordingHistogram(histogram("file-system-reads", Memory.Bytes))
+ val writes = DiffRecordingHistogram(histogram("file-system-writes", Memory.Bytes))
+
+ def sumOfAllFileSystems(sigar: Sigar, thunk: DiskUsage ⇒ Long): Long = {
+ val fileSystems = sigar.getFileSystemList.filter(_.getType == FileSystem.TYPE_LOCAL_DISK).map(_.getDevName).toSet
+ fileSystems.map(i ⇒ thunk(sigar.getDiskUsage(i))).fold(0L)(_ + _)
+ }
+
+ def update(sigar: Sigar): Unit = {
+ reads.record(sumOfAllFileSystems(sigar, _.getReadBytes))
+ writes.record(sumOfAllFileSystems(sigar, _.getWriteBytes))
+ }
+}
+
+object FileSystemMetrics extends SigarMetricRecorderCompanion("file-system") {
+ def apply(instrumentFactory: InstrumentFactory): FileSystemMetrics =
+ new FileSystemMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/LoadAverageMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/LoadAverageMetrics.scala
new file mode 100644
index 00000000..3e02cc8f
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/LoadAverageMetrics.scala
@@ -0,0 +1,25 @@
+package kamon.system.sigar
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.InstrumentFactory
+import org.hyperic.sigar.Sigar
+
+class LoadAverageMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) with SigarMetric {
+ val oneMinute = histogram("one-minute")
+ val fiveMinutes = histogram("five-minutes")
+ val fifteenMinutes = histogram("fifteen-minutes")
+
+ def update(sigar: Sigar): Unit = {
+ val loadAverage = sigar.getLoadAverage
+
+ oneMinute.record(loadAverage(0).toLong)
+ fiveMinutes.record(loadAverage(1).toLong)
+ fifteenMinutes.record(loadAverage(2).toLong)
+ }
+}
+
+object LoadAverageMetrics extends SigarMetricRecorderCompanion("load-average") {
+
+ def apply(instrumentFactory: InstrumentFactory): LoadAverageMetrics =
+ new LoadAverageMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/MemoryMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/MemoryMetrics.scala
new file mode 100644
index 00000000..ab7fcd88
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/MemoryMetrics.scala
@@ -0,0 +1,36 @@
+package kamon.system.sigar
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.{ Memory, InstrumentFactory }
+import org.hyperic.sigar.Sigar
+
+/**
+ * System memory usage metrics, as reported by Sigar:
+ * - used: Total used system memory.
+ * - free: Total free system memory (e.g. Linux plus cached).
+ * - swap-used: Total used system swap..
+ * - swap-free: Total free system swap.
+ */
+class MemoryMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) with SigarMetric {
+ val used = histogram("memory-used", Memory.Bytes)
+ val free = histogram("memory-free", Memory.Bytes)
+ val swapUsed = histogram("swap-used", Memory.Bytes)
+ val swapFree = histogram("swap-free", Memory.Bytes)
+
+ def update(sigar: Sigar): Unit = {
+ val mem = sigar.getMem
+ val swap = sigar.getSwap
+
+ used.record(mem.getUsed)
+ free.record(mem.getFree)
+ swapUsed.record(swap.getUsed)
+ swapFree.record(swap.getFree)
+ }
+}
+
+object MemoryMetrics extends SigarMetricRecorderCompanion("memory") {
+
+ def apply(instrumentFactory: InstrumentFactory): MemoryMetrics =
+ new MemoryMetrics(instrumentFactory)
+}
+
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/NetworkMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/NetworkMetrics.scala
new file mode 100644
index 00000000..fb33b7e4
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/NetworkMetrics.scala
@@ -0,0 +1,33 @@
+package kamon.system.sigar
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument._
+import org.hyperic.sigar.{ NetInterfaceStat, Sigar }
+
+class NetworkMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) with SigarMetric {
+ val receivedBytes = DiffRecordingHistogram(histogram("rx-bytes", Memory.Bytes))
+ val transmittedBytes = DiffRecordingHistogram(histogram("tx-bytes", Memory.Bytes))
+ val receiveErrors = DiffRecordingHistogram(histogram("rx-errors"))
+ val transmitErrors = DiffRecordingHistogram(histogram("tx-errors"))
+ val receiveDrops = DiffRecordingHistogram(histogram("rx-dropped"))
+ val transmitDrops = DiffRecordingHistogram(histogram("tx-dropped"))
+
+ def sumOfAllInterfaces(sigar: Sigar, thunk: NetInterfaceStat ⇒ Long): Long = {
+ val interfaces = sigar.getNetInterfaceList.toList.filter(_ != "lo")
+ interfaces.map(i ⇒ thunk(sigar.getNetInterfaceStat(i))).fold(0L)(_ + _)
+ }
+
+ def update(sigar: Sigar): Unit = {
+ receivedBytes.record(sumOfAllInterfaces(sigar, _.getRxBytes))
+ transmittedBytes.record(sumOfAllInterfaces(sigar, _.getTxBytes))
+ receiveErrors.record(sumOfAllInterfaces(sigar, _.getRxErrors))
+ transmitErrors.record(sumOfAllInterfaces(sigar, _.getTxErrors))
+ receiveDrops.record(sumOfAllInterfaces(sigar, _.getRxDropped))
+ transmitDrops.record(sumOfAllInterfaces(sigar, _.getTxDropped))
+ }
+}
+
+object NetworkMetrics extends SigarMetricRecorderCompanion("network") {
+ def apply(instrumentFactory: InstrumentFactory): NetworkMetrics =
+ new NetworkMetrics(instrumentFactory)
+} \ No newline at end of file
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/ProcessCpuMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/ProcessCpuMetrics.scala
new file mode 100644
index 00000000..0ca5c1c8
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/ProcessCpuMetrics.scala
@@ -0,0 +1,39 @@
+package kamon.system.sigar
+
+import kamon.metric.GenericEntityRecorder
+import kamon.metric.instrument.InstrumentFactory
+import org.hyperic.sigar.{ ProcCpu, Sigar }
+
+class ProcessCpuMetrics(instrumentFactory: InstrumentFactory) extends GenericEntityRecorder(instrumentFactory) with SigarMetric {
+ val processUserCpu = histogram("process-user-cpu")
+ val processSystemCpu = histogram("process-system-cpu")
+ val processTotalCpu = histogram("process-cpu")
+
+ var lastProcCpu: Option[ProcCpu] = None
+
+ def update(sigar: Sigar): Unit = {
+ val pid = sigar.getPid
+ val procCpu = sigar.getProcCpu(pid)
+
+ lastProcCpu.map { last ⇒
+ val timeDiff = procCpu.getLastTime - last.getLastTime
+ if (timeDiff > 0) {
+ val userPercent = (((procCpu.getUser - last.getUser) / timeDiff.toDouble) * 100).toLong
+ val systemPercent = (((procCpu.getSys - last.getSys) / timeDiff.toDouble) * 100).toLong
+
+ processUserCpu.record(userPercent)
+ processSystemCpu.record(systemPercent)
+ processTotalCpu.record(userPercent + systemPercent)
+ }
+ }
+
+ lastProcCpu = Some(procCpu)
+
+ }
+}
+
+object ProcessCpuMetrics extends SigarMetricRecorderCompanion("process-cpu") {
+
+ def apply(instrumentFactory: InstrumentFactory): ProcessCpuMetrics =
+ new ProcessCpuMetrics(instrumentFactory)
+}
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala
new file mode 100644
index 00000000..8a430427
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala
@@ -0,0 +1,59 @@
+package kamon.system.sigar
+
+import akka.actor.{ Props, Actor }
+import kamon.Kamon
+import kamon.metric.instrument.InstrumentFactory
+import kamon.metric.{ Entity, EntityRecorder, MetricsExtension, Metrics }
+import kamon.system.sigar.SigarMetricsUpdater.UpdateSigarMetrics
+import org.hyperic.sigar.Sigar
+
+import scala.concurrent.duration.FiniteDuration
+
+class SigarMetricsUpdater(refreshInterval: FiniteDuration) extends Actor {
+ val sigar = new Sigar
+ val metricsExtension = Kamon(Metrics)(context.system)
+
+ val sigarMetrics = List(
+ CpuMetrics.register(metricsExtension),
+ FileSystemMetrics.register(metricsExtension),
+ LoadAverageMetrics.register(metricsExtension),
+ MemoryMetrics.register(metricsExtension),
+ NetworkMetrics.register(metricsExtension),
+ ProcessCpuMetrics.register(metricsExtension))
+
+ val refreshSchedule = context.system.scheduler.schedule(refreshInterval, refreshInterval, self, UpdateSigarMetrics)(context.dispatcher)
+
+ def receive = {
+ case UpdateSigarMetrics ⇒ updateMetrics()
+ }
+
+ def updateMetrics(): Unit = {
+ sigarMetrics.foreach(_.update(sigar))
+ }
+
+ override def postStop(): Unit = {
+ refreshSchedule.cancel()
+ super.postStop()
+ }
+}
+
+object SigarMetricsUpdater {
+ def props(refreshInterval: FiniteDuration): Props =
+ Props(new SigarMetricsUpdater((refreshInterval)))
+
+ case object UpdateSigarMetrics
+}
+
+trait SigarMetric extends EntityRecorder {
+ def update(sigar: Sigar): Unit
+}
+
+abstract class SigarMetricRecorderCompanion(metricName: String) {
+ def register(metricsExtension: MetricsExtension): SigarMetric = {
+ val instrumentFactory = metricsExtension.instrumentFactory("system-metric")
+ metricsExtension.register(Entity(metricName, "system-metric"), apply(instrumentFactory)).recorder
+ }
+
+ def apply(instrumentFactory: InstrumentFactory): SigarMetric
+}
+