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

com.alibaba.metrics.os.windows.CpuUsageGaugeSet Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 com.alibaba.metrics.os.windows;

import com.alibaba.metrics.CachedMetricSet;
import com.alibaba.metrics.Clock;
import com.alibaba.metrics.Metric;
import com.alibaba.metrics.MetricName;
import com.alibaba.metrics.PersistentGauge;
import com.alibaba.metrics.os.utils.FormatUtils;
import org.hyperic.sigar.Cpu;
import org.hyperic.sigar.SigarException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.alibaba.metrics.os.utils.SystemInfoUtils.sigar;

public class CpuUsageGaugeSet extends CachedMetricSet {

    private static final Logger logger = LoggerFactory.getLogger(CpuUsageGaugeSet.class);

    private float[] cpuUsage;

    private CpuInfo lastCollectedCpuInfo;

    private enum CpuUsage {
        USER, NICE, SYSTEM, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST
    }

    /**
     * The "procs_running" line gives the number of processes currently running on CPUs.
     */
    private long processRunning;

    /**
     * The "procs_blocked" line gives the number of processes currently blocked, waiting for I/O to complete.
     */
    private long processBlocked;

    /**
     * The "intr" line gives counts of interrupts serviced since boot time,
     * for each of the possible system interrupts.
     * The first column is the total of all interrupts serviced;
     * each subsequent column is the total for that particular interrupt.
     */
    private long totalInterrupts;

    /**
     * The number of interrupts per second between collection
     * This is a equivalent implementation of 'in' in vmstat
     * https://www.thomas-krenn.com/en/wiki/Linux_Performance_Measurements_using_vmstat
     */
    private double interruptsRate;

    /**
     * The "ctxt" line gives the total number of context switches across all CPUs.
     */
    private long totalContextSwitches;

    /**
     * The number of context switches per second between collection
     * This is a equivalent implementation of 'cs' in vmstat
     * https://www.thomas-krenn.com/en/wiki/Linux_Performance_Measurements_using_vmstat
     */
    private double contextSwitchesRate;

    private Map gauges = new HashMap();

    public CpuUsageGaugeSet(long dataTTL, TimeUnit unit, Clock clock){
        super(dataTTL, unit, clock);
        cpuUsage = new float[CpuUsage.values().length];
        lastCollectedCpuInfo = new CpuInfo();
        populateMetrics();
    }

    public CpuUsageGaugeSet(long dataTTL, TimeUnit unit) {
        this(dataTTL, unit, Clock.defaultClock());
    }

    @Override
    public Map getMetrics() {
        return gauges;
    }

    private float getUsage(long current, long last, CpuInfo curInfo, CpuInfo lastInfo) {
        try {
            float f = 100.0f * (current - last) / (curInfo.totalTime - lastInfo.totalTime);
            return FormatUtils.formatFloat(f);
        } catch (Exception e) {
            return 0.0f;
        }
    }

    private CpuInfo collectCpuInfo() {

        //CpuPerc cpuList[] = sigar.getCpuPercList();

        Cpu cpu = null;
        try {
            cpu = sigar.getCpu();
        } catch (SigarException e) {

        }

        if (cpu == null){
            return new CpuInfo();
        }

        CpuInfo info = new CpuInfo();
        info.userTime = cpu.getUser();
        info.niceTime = cpu.getNice();
        info.systemTime = cpu.getSys();
        info.idleTime = cpu.getIdle();
        info.iowaitTime = cpu.getWait();
        info.irqTime = cpu.getIrq();
        info.softirqTime = cpu.getSoftIrq();
        info.stealTime = cpu.getStolen();

        info.totalTime = cpu.getTotal();

        return info;
    }

    @Override
    protected void getValueInternal() {

        CpuInfo current = collectCpuInfo();

        cpuUsage[CpuUsage.USER.ordinal()] =
                getUsage(current.userTime, lastCollectedCpuInfo.userTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.NICE.ordinal()] =
                getUsage(current.niceTime, lastCollectedCpuInfo.niceTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.SYSTEM.ordinal()] =
                getUsage(current.systemTime, lastCollectedCpuInfo.systemTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.IDLE.ordinal()] =
                getUsage(current.idleTime, lastCollectedCpuInfo.idleTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.IOWAIT.ordinal()] =
                getUsage(current.iowaitTime, lastCollectedCpuInfo.iowaitTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.IRQ.ordinal()] =
                getUsage(current.irqTime, lastCollectedCpuInfo.irqTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.SOFTIRQ.ordinal()] =
                getUsage(current.softirqTime, lastCollectedCpuInfo.softirqTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.STEAL.ordinal()] =
                getUsage(current.stealTime, lastCollectedCpuInfo.stealTime, current, lastCollectedCpuInfo);
        cpuUsage[CpuUsage.GUEST.ordinal()] =
                getUsage(current.guestTIme, lastCollectedCpuInfo.guestTIme, current, lastCollectedCpuInfo);

        lastCollectedCpuInfo = current;

    }


    private void populateMetrics() {

        gauges.put(MetricName.build("cpu.user"), new CpuGauge(CpuUsage.USER.ordinal()));
        gauges.put(MetricName.build("cpu.nice"), new CpuGauge(CpuUsage.NICE.ordinal()));
        gauges.put(MetricName.build("cpu.system"), new CpuGauge(CpuUsage.SYSTEM.ordinal()));
        gauges.put(MetricName.build("cpu.idle"), new CpuGauge(CpuUsage.IDLE.ordinal()));
        gauges.put(MetricName.build("cpu.iowait"), new CpuGauge(CpuUsage.IOWAIT.ordinal()));
        gauges.put(MetricName.build("cpu.irq"), new CpuGauge(CpuUsage.IRQ.ordinal()));
        gauges.put(MetricName.build("cpu.softirq"), new CpuGauge(CpuUsage.SOFTIRQ.ordinal()));
        gauges.put(MetricName.build("cpu.steal"), new CpuGauge(CpuUsage.STEAL.ordinal()));
        gauges.put(MetricName.build("cpu.guest"), new CpuGauge(CpuUsage.GUEST.ordinal()));

        gauges.put(MetricName.build("interrupts"), new PersistentGauge() {
            @Override
            public Double getValue() {
                refreshIfNecessary();
                return interruptsRate;
            }
        });

        gauges.put(MetricName.build("context_switches"), new PersistentGauge() {
            @Override
            public Double getValue() {
                refreshIfNecessary();
                return contextSwitchesRate;
            }
        });

        gauges.put(MetricName.build("process.running"), new PersistentGauge() {
            @Override
            public Long getValue() {
                refreshIfNecessary();
                return processRunning;
            }
        });

        gauges.put(MetricName.build("process.blocked"), new PersistentGauge() {
            @Override
            public Long getValue() {
                refreshIfNecessary();
                return processBlocked;
            }
        });
    }

    private class CpuGauge extends PersistentGauge {

        private int index;

        public CpuGauge(int index) {
            this.index = index;
        }

        @Override
        public Float getValue() {
            try {
                refreshIfNecessary();
                return cpuUsage[index];
            } catch (Exception e) {
                return 0.0f;
            }
        }
    }

    private class CpuInfo {
        /**
         * user: normal processes executing in user mode
         */
        long userTime;
        /**
         * nice: niced processes executing in user mode
         */
        long niceTime;
        /**
         * system: processes executing in kernel mode
         */
        long systemTime;
        /**
         * idle: twiddling thumbs
         */
        long idleTime;
        /**
         * iowait: In a word, iowait stands for waiting for I/O to complete. But there
             are several problems:
             1. Cpu will not wait for I/O to complete, iowait is the time that a task is
             waiting for I/O to complete. When cpu goes into idle state for
             outstanding task io, another task will be scheduled on this CPU.
             2. In a multi-core CPU, the task waiting for I/O to complete is not running
             on any CPU, so the iowait of each CPU is difficult to calculate.
             3. The value of iowait field in /proc/stat will decrease in certain
             conditions.
             So, the iowait is not reliable by reading from /proc/stat.
         */
        long iowaitTime;
        /**
         * irq: servicing interrupts
         */
        long irqTime;
        /**
         * softirq: servicing softirqs
         */
        long softirqTime;
        /**
         * steal: involuntary wait, since 2.6.11
         */
        long stealTime;
        /**
         * guest: running a normal guest, since 2.6.24
         */
        long guestTIme;
        /**
         * Total time
         */
        long totalTime;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy