/* ========================================================================================= * Copyright © 2013-2014 the kamon project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions * and limitations under the License. * ========================================================================================= */ package kamon.metric import akka.actor.ActorSystem import akka.testkit.{ TestKitBase, TestProbe } import com.typesafe.config.ConfigFactory import kamon.Kamon import kamon.metric.Subscriptions.TickMetricSnapshot import kamon.metrics.CPUMetrics.CPUMetricSnapshot import kamon.metrics.GCMetrics.GCMetricSnapshot import kamon.metrics.HeapMetrics.HeapMetricSnapshot import kamon.metrics.MemoryMetrics.MemoryMetricSnapshot import kamon.metrics.NetworkMetrics.NetworkMetricSnapshot import kamon.metrics.ProcessCPUMetrics.ProcessCPUMetricsSnapshot import kamon.metrics._ import kamon.system.SystemMetricsExtension import org.scalatest.{ Ignore, Matchers, WordSpecLike } import scala.concurrent.duration._ @Ignore class SystemMetricsSpec extends TestKitBase with WordSpecLike with Matchers { implicit lazy val system: ActorSystem = ActorSystem("system-metrics-spec", ConfigFactory.parseString( """ |akka { | extensions = ["kamon.system.SystemMetrics"] |} | |kamon.metrics { | | disable-aspectj-weaver-missing-error = true | | tick-interval = 1 second | | system { | cpu { | user { | highest-trackable-value = 999999999 | significant-value-digits = 2 | } | system { | highest-trackable-value = 999999999 | significant-value-digits = 2 | } | wait { | highest-trackable-value = 999999999 | significant-value-digits = 2 | } | idle { | highest-trackable-value = 999999999 | significant-value-digits = 2 | } | } | process-cpu { | user { | highest-trackable-value = 999999999 | significant-value-digits = 2 | } | system { | highest-trackable-value = 999999999 | significant-value-digits = 2 | } | } | memory { | used { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | free { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | buffer { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | cache { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | swap-used { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | swap-free { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | } | network { | rx-bytes { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | tx-bytes { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | rx-errors { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | tx-errors { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | } | heap { | used { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | max { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | committed { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | } | gc { | count { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | time { | highest-trackable-value = 3600000000000 | significant-value-digits = 2 | } | } | } |} """.stripMargin)) "the Kamon CPU Metrics" should { "record user, system, wait, idle metrics" in new CPUMetricsListenerFixture { val metricsListener = subscribeToMetrics() val CPUMetrics = expectCPUMetrics(metricsListener, 3 seconds) CPUMetrics.user.max should be >= 0L CPUMetrics.system.max should be >= 0L CPUMetrics.cpuWait.max should be >= 0L CPUMetrics.idle.max should be >= 0L } } "the Kamon GC Metrics" should { "record count, time metrics" in new GCMetricsListenerFixture { val metricsListener = subscribeToMetrics() val GCMetrics = expectGCMetrics(metricsListener, 3 seconds) GCMetrics.count.max should be > 0L GCMetrics.time.max should be > 0L } } "the Kamon Heap Metrics" should { "record used, max, commited metrics" in new HeapMetricsListenerFixture { val metricsListener = subscribeToMetrics() val HeapMetrics = expectHeapMetrics(metricsListener, 3 seconds) HeapMetrics.used.max should be >= 0L HeapMetrics.max.max should be >= 0L HeapMetrics.committed.max should be >= 0L } } "the Kamon Memory Metrics" should { "record used, free, buffer, cache, swap used, swap free metrics" in new MemoryMetricsListenerFixture { val metricsListener = subscribeToMetrics() val MemoryMetrics = expectMemoryMetrics(metricsListener, 3 seconds) MemoryMetrics.used.max should be >= 0L MemoryMetrics.free.max should be >= 0L MemoryMetrics.buffer.max should be >= 0L MemoryMetrics.cache.max should be >= 0L MemoryMetrics.swapUsed.max should be >= 0L MemoryMetrics.swapFree.max should be >= 0L } } "the Kamon Network Metrics" should { "record rxBytes, txBytes, rxErrors, txErrors metrics" in new NetworkMetricsListenerFixture { val metricsListener = subscribeToMetrics() val NetworkMetrics = expectNetworkMetrics(metricsListener, 3 seconds) NetworkMetrics.rxBytes.max should be >= 0L NetworkMetrics.txBytes.max should be >= 0L NetworkMetrics.rxErrors.max should be >= 0L NetworkMetrics.txErrors.max should be >= 0L } } "the Kamon Process CPU Metrics" should { "record user, system metrics" in new ProcessCPUMetricsListenerFixture { val metricsListener = subscribeToMetrics() val ProcessCPUMetrics = expectProcessCPUMetrics(metricsListener, 3 seconds) ProcessCPUMetrics.user.max should be > 0L ProcessCPUMetrics.system.max should be > 0L } } def expectCPUMetrics(listener: TestProbe, waitTime: FiniteDuration): CPUMetricSnapshot = { val tickSnapshot = within(waitTime) { listener.expectMsgType[TickMetricSnapshot] } val cpuMetricsOption = tickSnapshot.metrics.get(CPUMetrics(SystemMetricsExtension.CPU)) cpuMetricsOption should not be empty cpuMetricsOption.get.asInstanceOf[CPUMetricSnapshot] } trait CPUMetricsListenerFixture { def subscribeToMetrics(): TestProbe = { val metricsListener = TestProbe() Kamon(Metrics).subscribe(CPUMetrics, "*", metricsListener.ref, permanently = true) // Wait for one empty snapshot before proceeding to the test. metricsListener.expectMsgType[TickMetricSnapshot] metricsListener } } def expectGCMetrics(listener: TestProbe, waitTime: FiniteDuration): GCMetricSnapshot = { val tickSnapshot = within(waitTime) { listener.expectMsgType[TickMetricSnapshot] } val gcMetricsOption = tickSnapshot.metrics.get(GCMetrics(SystemMetricsExtension.garbageCollectors(0).getName)) gcMetricsOption should not be empty gcMetricsOption.get.asInstanceOf[GCMetricSnapshot] } trait GCMetricsListenerFixture { def subscribeToMetrics(): TestProbe = { val metricsListener = TestProbe() Kamon(Metrics).subscribe(GCMetrics, "*", metricsListener.ref, permanently = true) // Wait for one empty snapshot before proceeding to the test. metricsListener.expectMsgType[TickMetricSnapshot] metricsListener } } def expectHeapMetrics(listener: TestProbe, waitTime: FiniteDuration): HeapMetricSnapshot = { val tickSnapshot = within(waitTime) { listener.expectMsgType[TickMetricSnapshot] } val heapMetricsOption = tickSnapshot.metrics.get(HeapMetrics(SystemMetricsExtension.Heap)) heapMetricsOption should not be empty heapMetricsOption.get.asInstanceOf[HeapMetricSnapshot] } trait HeapMetricsListenerFixture { def subscribeToMetrics(): TestProbe = { val metricsListener = TestProbe() Kamon(Metrics).subscribe(HeapMetrics, "*", metricsListener.ref, permanently = true) // Wait for one empty snapshot before proceeding to the test. metricsListener.expectMsgType[TickMetricSnapshot] metricsListener } } def expectMemoryMetrics(listener: TestProbe, waitTime: FiniteDuration): MemoryMetricSnapshot = { val tickSnapshot = within(waitTime) { listener.expectMsgType[TickMetricSnapshot] } val memoryMetricsOption = tickSnapshot.metrics.get(MemoryMetrics(SystemMetricsExtension.Memory)) memoryMetricsOption should not be empty memoryMetricsOption.get.asInstanceOf[MemoryMetricSnapshot] } trait MemoryMetricsListenerFixture { def subscribeToMetrics(): TestProbe = { val metricsListener = TestProbe() Kamon(Metrics).subscribe(MemoryMetrics, "*", metricsListener.ref, permanently = true) // Wait for one empty snapshot before proceeding to the test. metricsListener.expectMsgType[TickMetricSnapshot] metricsListener } } def expectNetworkMetrics(listener: TestProbe, waitTime: FiniteDuration): NetworkMetricSnapshot = { val tickSnapshot = within(waitTime) { listener.expectMsgType[TickMetricSnapshot] } val networkMetricsOption = tickSnapshot.metrics.get(NetworkMetrics(SystemMetricsExtension.Network)) networkMetricsOption should not be empty networkMetricsOption.get.asInstanceOf[NetworkMetricSnapshot] } trait NetworkMetricsListenerFixture { def subscribeToMetrics(): TestProbe = { val metricsListener = TestProbe() Kamon(Metrics).subscribe(NetworkMetrics, "*", metricsListener.ref, permanently = true) // Wait for one empty snapshot before proceeding to the test. metricsListener.expectMsgType[TickMetricSnapshot] metricsListener } } def expectProcessCPUMetrics(listener: TestProbe, waitTime: FiniteDuration): ProcessCPUMetricsSnapshot = { val tickSnapshot = within(waitTime) { listener.expectMsgType[TickMetricSnapshot] } val processCPUMetricsOption = tickSnapshot.metrics.get(ProcessCPUMetrics(SystemMetricsExtension.ProcessCPU)) processCPUMetricsOption should not be empty processCPUMetricsOption.get.asInstanceOf[ProcessCPUMetricsSnapshot] } trait ProcessCPUMetricsListenerFixture { def subscribeToMetrics(): TestProbe = { val metricsListener = TestProbe() Kamon(Metrics).subscribe(ProcessCPUMetrics, "*", metricsListener.ref, permanently = true) // Wait for one empty snapshot before proceeding to the test. metricsListener.expectMsgType[TickMetricSnapshot] metricsListener } } }