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

org.yamcs.parameter.DiskstatsParameterProducer Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.parameter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.yamcs.logging.Log;
import org.yamcs.protobuf.Pvalue.AcquisitionStatus;
import org.yamcs.protobuf.Yamcs.Value.Type;
import org.yamcs.xtce.AggregateParameterType;
import org.yamcs.xtce.Member;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.UnitType;

import static org.yamcs.utils.ValueUtility.getFloatValue;

/**
 * Generates parameters containing information about the disk IO, similarly with what the command iostat provides.
 * 

* Works only on Linux, reads all the info from /proc/diskstats. * */ public class DiskstatsParameterProducer implements SystemParametersProducer { final static Log log = new Log(DiskstatsParameterProducer.class); final List diskstatsParams; private AggregateParameterType diskstatAggrType; public DiskstatsParameterProducer(SystemParametersService sysParamsService) throws IOException { UnitType kbsecunit = new UnitType("KB/s"); UnitType readsecunit = new UnitType("reads/s"); UnitType writesecunit = new UnitType("writes/s"); UnitType millisecunit = new UnitType("millis"); UnitType pctunit = new UnitType("%"); Member diskReadsMember = new Member("diskReads", sysParamsService.getBasicType(Type.FLOAT, readsecunit)); diskReadsMember.setShortDescription("Number of reads"); Member kbReadsMember = new Member("kbReads", sysParamsService.getBasicType(Type.FLOAT, kbsecunit)); kbReadsMember.setShortDescription("Amount of data read"); Member readWaitMember = new Member("readWait", sysParamsService.getBasicType(Type.FLOAT, millisecunit)); readWaitMember.setShortDescription("Average wait for a read"); Member diskWritesMember = new Member("diskWrites", sysParamsService.getBasicType(Type.FLOAT, writesecunit)); diskWritesMember.setShortDescription("Number of writes"); Member kbWritesMember = new Member("kbWrites", sysParamsService.getBasicType(Type.FLOAT, kbsecunit)); kbWritesMember.setShortDescription("Amount of data written"); Member writeWaitMember = new Member("writeWait", sysParamsService.getBasicType(Type.FLOAT, millisecunit)); writeWaitMember.setShortDescription("Average wait for a write"); Member utilMember = new Member("util", sysParamsService.getBasicType(Type.FLOAT, pctunit)); utilMember.setShortDescription("Percentage of elapsed time during which " + "I/O requests were issued to the device"); diskstatAggrType = new AggregateParameterType.Builder().setName("DiskStats") .addMember(diskReadsMember) .addMember(kbReadsMember) .addMember(readWaitMember) .addMember(diskWritesMember) .addMember(kbWritesMember) .addMember(writeWaitMember) .addMember(utilMember) .build(); diskstatsParams = new ArrayList<>(); for (var me : readStats().entrySet()) { String device = me.getKey(); Parameter p = sysParamsService.createSystemParameter("diskstats/" + device, diskstatAggrType, "Disk statistics for " + device); diskstatsParams.add(new DiskStatsParam(device, p, me.getValue())); } } @Override public Collection getSystemParameters(long gentime) { List pvlist = new ArrayList<>(); try { Map stats = readStats(); for (DiskStatsParam ioparam : diskstatsParams) { var s1 = stats.get(ioparam.devName); if (s1 == null) { continue; } var s0 = ioparam.stats; float timeMillis = (float) ((s1.nanoTime - s0.nanoTime) / 1000_000.0); float timeSec = timeMillis / 1000f; if (timeSec < 0) { return pvlist; } AggregateValue v = new AggregateValue(diskstatAggrType.getMemberNames()); v.setMemberValue("diskReads", getFloatValue((s1.diskReads - s0.diskReads) / timeSec)); v.setMemberValue("kbReads", getFloatValue((s1.sectorReads - s0.sectorReads) / timeSec / 2f)); float readWait = s1.diskReads > s0.diskReads ? (s1.readTime - s0.readTime) / (float) (s1.diskReads - s0.diskReads) : 0; v.setMemberValue("readWait", getFloatValue(readWait)); v.setMemberValue("diskWrites", getFloatValue((s1.diskWrites - s0.diskWrites) / timeSec)); v.setMemberValue("kbWrites", getFloatValue((s1.sectorWrites - s0.sectorWrites) / timeSec / 2f)); float writeWait = s1.diskWrites > s0.diskWrites ? (s1.writeTime - s0.writeTime) / (float) (s1.diskWrites - s0.diskWrites) : 0; v.setMemberValue("writeWait", getFloatValue(writeWait)); v.setMemberValue("util", getFloatValue((s1.ioTime - s0.ioTime) / timeSec / 10f)); ParameterValue pv = new ParameterValue(ioparam.param); pv.setGenerationTime(gentime); pv.setAcquisitionTime(gentime); pv.setAcquisitionStatus(AcquisitionStatus.ACQUIRED); pv.setEngValue(v); pv.setExpireMillis((long) (1.9 * getFrequency() * 1000)); pvlist.add(pv); ioparam.stats = s1; } } catch (IOException e) { log.error("Failed to collect disk statistics", e); } return pvlist; } Map readStats() throws IOException { Map r = new HashMap<>(); try (BufferedReader reader = new BufferedReader(new FileReader("/proc/diskstats"))) { String line; while ((line = reader.readLine()) != null) { long nanoTime = System.nanoTime(); String[] parts = line.trim().split("\\s+"); if (parts.length < 14) { continue; } if ("7".equals(parts[0])) { // skip loopback devices continue; } String device = parts[2]; DiskStat stat = new DiskStat(nanoTime, Long.parseLong(parts[3]), Long.parseLong(parts[5]), Long.parseLong(parts[6]), Long.parseLong(parts[7]), Long.parseLong(parts[9]), Long.parseLong(parts[10]), Long.parseLong(parts[12])); r.put(device, stat); } } return r; } public long uptime() throws IOException { try (BufferedReader reader = new BufferedReader(new FileReader("/proc/uptime"))) { String line = reader.readLine(); String[] parts = line.trim().split("\\s+"); double uptimeSeconds = Double.parseDouble(parts[0]); return (long) (uptimeSeconds * 1000); } } @Override public int getFrequency() { return 5; } static class DiskStatsParam { final String devName; final Parameter param; DiskStat stats; public DiskStatsParam(String devName, Parameter param, DiskStat stats) { this.devName = devName; this.param = param; this.stats = stats; } } static class DiskStat { final long nanoTime; final long sectorReads; final long diskReads; final long readTime; final long diskWrites; final long sectorWrites; final long writeTime; final long ioTime; public DiskStat(long nanoTime, long diskReads, long sectorReads, long readTime, long diskWrites, long sectorWrites, long writeTime, long ioTime) { this.nanoTime = nanoTime; this.diskReads = diskReads; this.sectorReads = sectorReads; this.readTime = readTime; this.sectorWrites = sectorWrites; this.diskWrites = diskWrites; this.writeTime = writeTime; this.ioTime = ioTime; } @Override public String toString() { return "DiskStat [nanoTime=" + nanoTime + ", sectorReads=" + sectorReads + ", diskReads=" + diskReads + ", readTime=" + readTime + ", diskWrites=" + diskWrites + ", sectorWrites=" + sectorWrites + ", writeTime=" + writeTime + ", ioTime=" + ioTime + "]"; } } public static boolean hasDisksStats() { return new File("/proc/diskstats").canRead(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy