All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kamon.system.host.ContextSwitchesMetrics.scala Maven / Gradle / Ivy

There is a newer version: 2.7.5
Show newest version
/*
 * =========================================================================================
 * Copyright © 2013-2017 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.system.host

import java.io.IOException
import java.nio.charset.StandardCharsets.US_ASCII
import java.nio.file.{Files, Paths}

import kamon.Kamon
import kamon.system.{CustomMetricBuilder, Metric, MetricBuilder}
import kamon.util.DifferentialSource
import org.slf4j.Logger

import scala.collection.JavaConverters.iterableAsScalaIterableConverter

/**
 *  Context Switches metrics:
 *    - process-voluntary: Total number of voluntary context switches related to the current process (one thread explicitly yield the CPU to another).
 *    - process-non-voluntary: Total number of involuntary context switches related to the current process (the system scheduler suspends and active thread, and switches control to a different thread).
 *    - global:  Total number of context switches across all CPUs.
 */
object ContextSwitchesMetrics extends MetricBuilder("host.context-switches") with CustomMetricBuilder {
  def build(pid: Long, metricName: String, logger: Logger)  = new Metric {
    val contextSwitchMetric = Kamon.counter(metricName)

    val perProcessVoluntaryMetric     = contextSwitchMetric.refine(Map("component" -> "system-metrics", "mode" -> "process-voluntary"))
    val perProcessNonVoluntaryMetric  = contextSwitchMetric.refine(Map("component" -> "system-metrics", "mode" -> "process-non-voluntary"))
    val globalMetric                  = contextSwitchMetric.refine(Map("component" -> "system-metrics", "mode" -> "global"))

    val globalContextSwitchSource = DifferentialSource(() => contextSwitches)

    override def update(): Unit = {
      val (voluntary, nonVoluntary) = contextSwitchesByProcess(pid)
      perProcessVoluntaryMetric.increment(voluntary)
      perProcessNonVoluntaryMetric.increment(nonVoluntary)
      globalMetric.increment(globalContextSwitchSource.get())
    }

    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), 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 _: IOException ⇒ logger.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), US_ASCII).asScala.toList) {
          if (line.startsWith("ctxt")) {
            contextSwitches = line.substring(line.indexOf(" ") + 1).toLong
          }
        }
      } catch {
        case _: IOException ⇒ logger.error("Error trying to read [{}]", filename)
      }
      contextSwitches
    }

  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy