![JAR search and dependency download from the Maven repository](/logo.png)
com.bigdata.counters.linux.VMStatCollector Maven / Gradle / Ivy
/*
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Dec 9, 2008
*/
package com.bigdata.counters.linux;
import com.bigdata.counters.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
/**
* Collects some counters using vmstat
.
*
* @author Bryan Thompson
*/
public class VMStatCollector extends AbstractProcessCollector implements
ICounterHierarchy, IRequiredHostCounters, IHostCounters{
/**
* Inner class integrating the current values with the {@link ICounterSet}
* hierarchy.
*
* @author Bryan
* Thompson
*/
abstract class I implements IInstrument {
protected final String path;
public String getPath() {
return path;
}
public I(final String path) {
if (path == null)
throw new IllegalArgumentException();
this.path = path;
}
@Override
public long lastModified() {
return lastModified.get();
}
/**
* @throws UnsupportedOperationException
* always.
*/
@Override
public void setValue(final T value, final long timestamp) {
throw new UnsupportedOperationException();
}
}
/**
* Double precision counter with scaling factor.
*
* @author Bryan Thompson
*/
class DI extends I {
protected final double scale;
DI(final String path, final double scale) {
super(path);
this.scale = scale;
}
@Override
public Double getValue() {
final Double value = (Double) vals.get(path);
// no value is defined.
if (value == null)
return 0d;
final double d = value.doubleValue() * scale;
return d;
}
}
/**
* Map containing the current values for the configured counters. The keys
* are paths into the {@link CounterSet}. The values are the data most
* recently read from vmstat
.
*/
final private Map vals = new ConcurrentHashMap();
/**
* The timestamp associated with the most recently collected values.
*/
private final AtomicLong lastModified = new AtomicLong(
System.currentTimeMillis());
/**
* true
iff you want collect the user time, system time,
* and IO WAIT time using vmstat (as opposed to sar).
*/
private final boolean cpuStats;
/**
* The {@link Pattern} used to split apart the rows read from
* vmstat
.
*/
// Note: Exposed to the test suite.
final static Pattern pattern = Pattern.compile("\\s+");
/**
*
* @param interval
* The interval for the collected statistics.
* @param cpuStats
* true
iff you want collect the user time, system
* time, and IO WAIT time using vmstat (as opposed to sar).
*/
public VMStatCollector(final int interval, boolean cpuStats) {
super(interval);
this.cpuStats = cpuStats;
}
@Override
public List getCommand() {
final List command = new LinkedList();
command.add("/usr/bin/vmstat");
// Note: switch indicats that the header will be displayed only once.
command.add("-n");
// Note: The configured interval in seconds between reports.
command.add(""+getInterval());
return command;
}
/**
* Declares the counters that we will collect
*/
@Override
public CounterSet getCounters() {
@SuppressWarnings("rawtypes")
final List inst = new LinkedList();
/*
* Note: Counters are all declared as Double to facilitate aggregation.
*/
/*
* Note: [si] is "the #of blocks swapped in per second."
*/
inst.add(new DI(IRequiredHostCounters.Memory_majorFaultsPerSecond, 1d));
/*
* Note: [swpd] is "the amount of virtual memory used". The counter is
* reported in 1024 byte blocks, so we convert to bytes using a scaling
* factor.
*
* @todo where do I get the amount of swap space available?
*/
inst.add(new DI(IHostCounters.Memory_SwapBytesUsed, 1024d));
/*
* Note: [free] is "the amount of idle memory". The counter is reported
* in 1024 byte blocks, so we convert to bytes using a scaling factor.
*/
inst.add(new DI(IHostCounters.Memory_Bytes_Free, 1024d));
/*
* Note: [bi] is "the blocks received from a device / second". The
* counter is reported in 1024 byte blocks, so we convert to bytes using
* a scaling factor.
*/
inst.add(new DI(IRequiredHostCounters.PhysicalDisk_BytesReadPerSec,
1024d));
/*
* Note: [bo] is "the blocks sent to a device / second". The counter is
* reported in 1024 byte blocks, so we convert to bytes using a scaling
* factor.
*/
inst.add(new DI(IRequiredHostCounters.PhysicalDisk_BytesWrittenPerSec,
1024d));
if (cpuStats) {
/*
* Note: vmstat reports percentages in [0:100] so we convert them to
* [0:1] using a scaling factor.
*/
// Note: processor time = (100-idle), converted to [0:1].
inst.add(new DI(IRequiredHostCounters.CPU_PercentProcessorTime,
.01d));
// Note: column us
inst.add(new DI(IHostCounters.CPU_PercentUserTime, .01d));
// Note: column sy
inst.add(new DI(IHostCounters.CPU_PercentSystemTime, .01d));
// Note: column wa
inst.add(new DI(IHostCounters.CPU_PercentIOWait, .01d));
}
final CounterSet root = new CounterSet();
for (@SuppressWarnings("rawtypes") I i : inst) {
root.addCounter(i.getPath(), i);
}
return root;
}
@Override
public AbstractProcessReader getProcessReader() {
return new VMStatReader();
}
/**
* Sample output for vmstat -n 1
, where -n
* suppresses the repeat of the header and 1
is the interval.
*
*
* procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
* r b swpd free buff cache si so bi bo in cs us sy id wa st
* 1 0 96 178580 206520 1170604 0 0 0 7 1 0 1 0 99 0 0
* 0 0 96 178572 206520 1170608 0 0 0 0 4 619 2 0 98 0 0
* 0 0 96 178572 206520 1170608 0 0 0 0 22 574 1 0 100 0 0
* 0 0 96 178572 206520 1170608 0 0 0 0 53 615 1 0 99 0 0
* 0 0 96 178572 206520 1170608 0 0 0 0 20 570 1 0 99 0 0
* 0 0 96 178324 206520 1170608 0 0 0 80 15 584 0 0 99 0 0
*
*
* @author Bryan Thompson
*/
private class VMStatReader extends ProcessReaderHelper {
private static final String VMSTAT_FIELD_SWPD = "swpd";
private static final String VMSTAT_FIELD_FREE = "free";
private static final String VMSTAT_FIELD_SI = "si";
private static final String VMSTAT_FIELD_SO = "so";
private static final String VMSTAT_FIELD_BI = "bi";
private static final String VMSTAT_FIELD_BO = "bo";
private static final String VMSTAT_FIELD_US = "us";
private static final String VMSTAT_FIELD_SY = "sy";
private static final String VMSTAT_FIELD_ID = "id";
private static final String VMSTAT_FIELD_WA = "wa";
@Override
protected ActiveProcess getActiveProcess() {
if (activeProcess == null)
throw new IllegalStateException();
return activeProcess;
}
public VMStatReader() {
super();
}
@Override
protected void readProcess() throws Exception {
if(log.isInfoEnabled())
log.info("begin");
for (int i = 0; i < 10 && !getActiveProcess().isAlive(); i++) {
if(log.isInfoEnabled())
log.info("waiting for the readerFuture to be set.");
Thread.sleep(100/*ms*/);
}
if(log.isInfoEnabled())
log.info("running");
// skip 1st header.
{
final String header = readLine();
if (log.isInfoEnabled())
log.info("header: " + header);
}
// read 2nd header and verify expected fields.
final String header;
{
header = readLine();
if (log.isInfoEnabled())
log.info("header: " + header);
}
// read lines until interrupted.
while(true) {
// data.
final String data = readLine();
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (fields)
// r b swpd free buff cache si so bi bo in cs us sy id wa st (header)
// 1 0 96 178580 206520 1170604 0 0 0 7 1 0 1 0 99 0 0 (data)
try {
// timestamp
lastModified.set(System.currentTimeMillis());
final Map fields = SysstatUtil.getDataMap(header, data);
if (log.isInfoEnabled())
log.info("\nswpd=" + fields.get(VMSTAT_FIELD_SWPD) + ", free=" + fields.get(VMSTAT_FIELD_FREE) + ", si="
+ fields.get(VMSTAT_FIELD_SI) + ", so=" + fields.get(VMSTAT_FIELD_SO) + ", bi=" + fields.get(VMSTAT_FIELD_BI) + ", bo="
+ fields.get(VMSTAT_FIELD_BO) + ", %user=" + fields.get(VMSTAT_FIELD_US) + ", %system="
+ fields.get(VMSTAT_FIELD_SY) + ", idle=" + fields.get(VMSTAT_FIELD_ID) + ", iowait="
+ fields.get(VMSTAT_FIELD_WA) + "\n" + header + "\n" + data);
vals.put(IHostCounters.Memory_SwapBytesUsed, Double
.parseDouble(fields.get(VMSTAT_FIELD_SWPD)));
vals.put(IHostCounters.Memory_Bytes_Free, Double
.parseDouble(fields.get(VMSTAT_FIELD_FREE)));
vals.put(IRequiredHostCounters.Memory_majorFaultsPerSecond, Double
.parseDouble(fields.get(VMSTAT_FIELD_SI)));
vals.put(IRequiredHostCounters.PhysicalDisk_BytesReadPerSec, Double
.parseDouble(fields.get(VMSTAT_FIELD_BI)));
vals.put(IRequiredHostCounters.PhysicalDisk_BytesWrittenPerSec, Double
.parseDouble(fields.get(VMSTAT_FIELD_BO)));
if (cpuStats) {
vals.put(IHostCounters.CPU_PercentUserTime, Double
.parseDouble(fields.get(VMSTAT_FIELD_US)));
vals.put(IHostCounters.CPU_PercentSystemTime, Double
.parseDouble(fields.get(VMSTAT_FIELD_SY)));
vals.put(IHostCounters.CPU_PercentIOWait, Double
.parseDouble(fields.get(VMSTAT_FIELD_WA)));
vals.put(
IRequiredHostCounters.CPU_PercentProcessorTime,
(100d - Double.parseDouble(fields.get(VMSTAT_FIELD_ID))));
}
} catch (Exception ex) {
/*
* Issue warning for parsing problems.
*/
log.warn(ex.getMessage() //
+ "\nheader: " + header //
+ "\n data: " + data //
, ex);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy