/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. 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. */ package org.hyperic.hq.plugin.system; import java.util.Arrays; import java.util.List; import java.util.Properties; import org.hyperic.hq.measurement.data.TopNConfigurationProperties; import org.hyperic.hq.plugin.mssql.PDH; import org.hyperic.hq.product.Collector; import org.hyperic.hq.product.LogTrackPlugin; import static org.hyperic.hq.product.MeasurementPlugin.TYPE_COLLECTOR; import org.hyperic.hq.product.Metric; import org.hyperic.hq.product.MetricInvalidException; import org.hyperic.hq.product.MetricNotFoundException; import org.hyperic.hq.product.MetricUnreachableException; import org.hyperic.hq.product.MetricValue; import org.hyperic.hq.product.PluginException; import org.hyperic.hq.product.SigarMeasurementPlugin; import org.hyperic.hq.product.TypeInfo; import org.hyperic.sigar.FileInfo; import org.hyperic.sigar.FileSystem; import org.hyperic.sigar.FileSystemUsage; import org.hyperic.sigar.NetFlags; import org.hyperic.sigar.ProcState; import org.hyperic.sigar.Sigar; import org.hyperic.sigar.SigarException; import org.hyperic.sigar.ptql.ProcessQuery; import org.hyperic.sigar.ptql.ProcessQueryFactory; import org.hyperic.sigar.win32.Pdh; import org.hyperic.sigar.win32.Win32Exception; import org.hyperic.util.config.ConfigResponse; import org.hyperic.util.config.ConfigSchema; public class SystemMeasurementPlugin extends SigarMeasurementPlugin { private void reportError(Metric metric, Exception e) { getLog().error(metric + ": " + e.getMessage(), e); getManager().reportEvent(metric, System.currentTimeMillis(), LogTrackPlugin.LOGLEVEL_ERROR, "system", e.getMessage()); } private MetricValue getPdhValue(Metric metric) throws PluginException { String obj = "\\" + metric.getObjectPropString() + "\\" + metric.getAttributeName(); Double val; try { val = new Pdh().getRawValue(obj); return new MetricValue(val); }catch(Win32Exception e) { throw new PluginException(e); } } private MetricValue getPdhValue2(Metric metric) { String prop = metric.getObjectPropString().replaceAll("%3A", ":"); prop = prop.replaceAll("%26", "&"); String obj = "\\" + prop + "\\"; if (metric.getAttributeName().startsWith("Memory ")) { obj += metric.getAttributeName().replace("Memory ", ""); } else { obj += metric.getAttributeName(); } getLog().debug("[getPdhValue2] obj=" + obj); Double val = Double.NaN; try { val = PDH.getValue(obj); } catch (PluginException e) { getLog().debug("[getPdhValue2] obj=" + obj + " error:"+e,e); } return new MetricValue(val); } @Override public MetricValue getValue(Metric metric) throws PluginException, MetricNotFoundException, MetricUnreachableException { getLog().debug("[getValue] '" + getTypeInfo().getName() + "' metric:" + metric); //nira: should be first!! since Type is not configured String domain = metric.getDomainName(); if (domain.equals("blockdev") || domain.equals("page")) { return Collector.getValue(this, metric); } if (domain.equals("pdh2")) { if ("formated".equals(metric.getObjectProperties().get("type"))) { return Collector.getValue(this, metric); } else { return getPdhValue2(metric); } } if (domain.equalsIgnoreCase("calculated")) { double res = 0; try { FileSystem[] fslist = getSigar().getFileSystemList(); for (FileSystem fs : fslist) { if (fs.getType() == FileSystem.TYPE_LOCAL_DISK) { getLog().debug("[calculated] fs: " + fs.getDirName()); FileSystemUsage fsu = getSigar().getMountedFileSystemUsage(fs.getDirName()); if (metric.getAttributeName().equals("capacity")) { res += fsu.getTotal(); } else if (metric.getAttributeName().equals("usage")) { res += fsu.getUsed(); } else { getLog().debug("[calculated] " + metric.getAttributeName() + " not supported."); return MetricValue.NONE; } } } } catch (SigarException ex) { getLog().debug(ex, ex); } return new MetricValue(res); } if (domain.equals("disk.avail")) { return getDiskAvail(metric); } if (domain.equals("pdh")) { return getPdhValue(metric); } Properties props = metric.getObjectProperties(); String type = props.getProperty("Type"); // TalG: Fix HHQ-5967- check for null if (type == null){ String errMsg = "No type for metric [" + metric.getAttributeName() + "]"; throw new MetricNotFoundException(errMsg); } boolean isFsUsage = type.endsWith("FileSystemUsage"); if (domain.equals("sigar.ext")) { if (type.equals("CpuInfo")) { return new MetricValue(getNumCpus()); } else if (type.equals("DiskUsage")) { //back-compat w/ old template String arg = props.getProperty("Arg"); return new MetricValue(getDiskUsage(arg)); } else if (type.equals("ChildProcesses")) { String arg = props.getProperty("Arg"); return new MetricValue(getChildProcessCount(arg)); } else if (type.equals("FileSystemInfo")) { return new MetricValue(getAverageReadWrites()); } } //else better be "system.avail" if (type.equals("Platform")) { return new MetricValue(Metric.AVAIL_UP); } if (type.equals("NetIfconfig")) { double avail; int value = (int)super.getValue(metric).getValue(); if (((value & NetFlags.IFF_UP) > 0) && ((value & NetFlags.IFF_RUNNING) == NetFlags.IFF_RUNNING)) { avail = Metric.AVAIL_UP; } else if ((value & NetFlags.IFF_UP) > 0 ) { avail = Metric.AVAIL_WARN; } else { avail = Metric.AVAIL_DOWN; } return new MetricValue(avail); } if (isFsUsage) { double avail; try { super.getValue(metric).getValue(); avail = Metric.AVAIL_UP; } catch (Exception e) { avail = Metric.AVAIL_DOWN; reportError(metric, e); } return new MetricValue(avail); } if (type.equals("FileInfo") || type.equals("DirStats")) { String attr = metric.getAttributeName(); double avail; try { double val = super.getValue(metric).getValue(); avail = Metric.AVAIL_UP; //for directories, verify the type. if (attr.equals("Type") && (val != FileInfo.TYPE_DIR)) { avail = Metric.AVAIL_DOWN; } } catch (MetricNotFoundException e) { //SigarFileNotFoundException avail = Metric.AVAIL_DOWN; } return new MetricValue(avail); } if (type.equals("CpuPercList")) { try { super.getValue(metric); // If we can get the metric, return avail up return new MetricValue(Metric.AVAIL_UP); } catch (Exception e) { return new MetricValue(Metric.AVAIL_DOWN); } } if (type.equals("MultiProcCpu")) { double val = super.getValue(metric).getValue(); if (val >= 1) { return new MetricValue(Metric.AVAIL_UP); } else { return new MetricValue(Metric.AVAIL_DOWN); } } throw new MetricNotFoundException(metric.toString()); } private MetricValue getDiskAvail(Metric metric) { MetricValue res = new MetricValue(Metric.AVAIL_DOWN); String disk = metric.getObjectProperty("disk"); String type = metric.getObjectProperty("type"); try { List<String> disks = Arrays.asList(Pdh.getInstances(type+"Disk")); getLog().debug("[getDiskAvail]("+type+") disk='"+disk+"' disks="+disks); if(disks.contains(disk)) { res = new MetricValue(Metric.AVAIL_UP); } } catch (Win32Exception ex) { getLog().debug("[getDiskAvail]("+type+") " + ex, ex); } return res; } private MetricValue getAverageReadWrites() { try { Sigar sigar = getSigar(); FileSystem[] fslist = sigar.getFileSystemList(); long totalReadWrites = 0; boolean found = false; int numOfFs = 0; for (int i=0; i<fslist.length; i++) { FileSystem fs = fslist[i]; if (fs.getType() == FileSystem.TYPE_LOCAL_DISK) { numOfFs++; String dirName = fs.getDirName(); FileSystemUsage fsUsage = sigar.getMountedFileSystemUsage(dirName); if (fsUsage != null) { long reads = fsUsage.getDiskReads(); if (reads >= 0) { found = true; totalReadWrites += reads; } long writes = fsUsage.getDiskWrites(); if (writes >= 0) { totalReadWrites += writes; found = true; } } } } if (found) { double averageReadsWrites = ((double)totalReadWrites)/ numOfFs; return new MetricValue(averageReadsWrites); } else { return MetricValue.NONE; } } catch(Exception e) { return MetricValue.NONE; } } private double getChildProcessCount(String arg) throws MetricNotFoundException { try { Sigar s = getSigar(); long processIds[] = s.getProcList(); ProcessQuery query = ProcessQueryFactory.getInstance().getQuery(arg); long parentPid = query.findProcess(s); double count = 0; for (long pid : processIds) { ProcState state; try { state = s.getProcState(pid); if (parentPid == state.getPpid()) { count++; } } catch (SigarException e) { //ok, Process likely went away } } return count; } catch (Exception e) { throw new MetricNotFoundException(e.getMessage(), e); } } private double getNumCpus() throws MetricNotFoundException { try { return getSigar().getCpuInfoList().length; } catch (Exception e) { throw new MetricNotFoundException(e.getMessage(), e); } } private long getDiskUsage(String arg) throws MetricNotFoundException { try { return getSigar().getDirUsage(arg).getDiskUsage(); } catch (Exception e) { throw new MetricNotFoundException(e.getMessage(), e); } } @Override public ConfigSchema getConfigSchema(TypeInfo info, ConfigResponse config) { ConfigSchema schema = new ConfigSchema(); if (info.getType() == TypeInfo.TYPE_PLATFORM) { if (config.getKeys().contains(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName()) || config.getKeys().isEmpty()) { for (TopNConfigurationProperties conf : TopNConfigurationProperties.values()) { schema.addOption(conf.getConfigOption()); } } } return schema; } @Override public Collector getNewCollector() { getLog().debug("[getNewCollector] type: " + getTypeInfo().getName()); if (getPluginData().getPlugin(TYPE_COLLECTOR, getTypeInfo().getName()) == null) { getPluginData().addPlugin(TYPE_COLLECTOR, "Win32", SystemPDHCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "Win-Hyper-V", SystemPDHCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "Linux", LinuxVMStatsCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "Solaris", OtherUnixCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "AIX", OtherUnixCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "HPUX", OtherUnixCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "FileServer Physical Disk", SystemPDHCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, "FileServer Logical Disk", SystemPDHCollector.class.getName()); getPluginData().addPlugin(TYPE_COLLECTOR, SystemPlugin.BLOCK_DEVICE_SERVICE, LinuxCollector.class.getName()); } try { return super.getNewCollector(); } catch (MetricInvalidException ex) { getLog().debug("[getNewCollector] " + ex.getMessage(), ex); throw ex; } } }