From e3ff68809b31dd673aefa5b605d70bd40bc2c1d9 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 30 Jan 2015 00:54:57 -0300 Subject: = system-metrics: fix ProcessCpuMetrics usage in order to show the percent usage shared in the numbers of cpu cores --- .../kamon/system/sigar/ProcessCpuMetrics.scala | 50 ++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'kamon-system-metrics/src') 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 index 4f197c8f..436fadda 100644 --- a/kamon-system-metrics/src/main/scala/kamon/system/sigar/ProcessCpuMetrics.scala +++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/ProcessCpuMetrics.scala @@ -25,31 +25,47 @@ class ProcessCpuMetrics(sigar: Sigar, instrumentFactory: InstrumentFactory) exte val processSystemCpu = histogram("process-system-cpu") val processTotalCpu = histogram("process-cpu") - var lastProcCpu: Option[ProcCpu] = None + val pid = sigar.getPid + val totalCores = sigar.getCpuInfoList.headOption.map(_.getTotalCores.toLong).getOrElse(1L) + var lastProcCpu: ProcCpu = sigar.getProcCpu(pid) + var currentLoad: Long = 0 + + /** + * While CPU usage time updates not very often, We have introduced a simple heuristic, that supposes that the load is the same as previous, + * while CPU usage time doesn't update. But supposing that it could be zero load for a process for some time, + * We used an arbitrary duration of 2000 milliseconds, after which the same CPU usage time value become legal, and it is supposed that the load is really zero. + * + * @see [[http://stackoverflow.com/questions/19323364/using-sigar-api-to-get-jvm-cpu-usage "Stack Overflow: Using Sigar API to get JVM Cpu usage"]] + */ def update(): 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) - } - } + val currentProcCpu = sigar.getProcCpu(pid) + val totalDiff = currentProcCpu.getTotal - lastProcCpu.getTotal + val userDiff = currentProcCpu.getUser - lastProcCpu.getUser + val systemDiff = currentProcCpu.getSys - lastProcCpu.getSys + val timeDiff = currentProcCpu.getLastTime - lastProcCpu.getLastTime + + def percentUsage(delta: Long): Long = 100 * delta / timeDiff / totalCores - lastProcCpu = Some(procCpu) + if (totalDiff == 0) { + if (timeDiff > 2000) currentLoad = 0 + if (currentLoad == 0) lastProcCpu = currentProcCpu + } else { + val totalPercent = percentUsage(totalDiff) + val userPercent = percentUsage(userDiff) + val systemPercent = percentUsage(systemDiff) + processUserCpu.record(userPercent) + processSystemCpu.record(systemPercent) + processTotalCpu.record(userPercent + systemPercent) + + currentLoad = totalPercent + lastProcCpu = currentProcCpu + } } } object ProcessCpuMetrics extends SigarMetricRecorderCompanion("process-cpu") { - def apply(sigar: Sigar, instrumentFactory: InstrumentFactory): ProcessCpuMetrics = new ProcessCpuMetrics(sigar, instrumentFactory) } -- cgit v1.2.3