/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2007, Helios Development Group and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.helios.collector.ping;
import org.helios.collector.core.AbstractCollector;
import org.helios.collector.core.CollectionResult;
import org.helios.collector.core.CollectorException;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Title: PingCollector</p>
* <p>Description: Ping Time Collector</p>
* <p>Company: Helios Development Group</p>
* @author Whitehead(whitehead.nicholas@gmail.com)
* Sandeep Malhotra (smalhotra@heliosdev.org)
*/
@ManagedResource
public class PingCollector extends AbstractCollector {
/** PingCollector collector version */
private static final String PING_COLLECTOR_VERSION="0.1";
/** true if platform is windows */
protected boolean isWindows = true;
/** A list of servers to ping */
protected List<String> servers = new ArrayList<String>();
/** The packet size of each ping. Defaults to 32 */
protected int packetSize = 32;
/** The number of packets to be sent. Defaults to 2 */
protected int packetCount = 1;
/** The timeout in seconds for each request. Defaults to 5 */
protected int timeout = 5;
public CollectionResult collectCallback() {
long start = System.currentTimeMillis();
CollectionResult result = new CollectionResult();
try{
for(String s: servers) {
String[] fragment = s.split("\\|");
String ip = fragment[0].trim();
String name = fragment[1].trim();
String output = ping(ip);
if(isWindows) {
processWindowsPing(output, name);
} else {
processLinuxPing(output, name);
}
}
result.setResultForLastCollection(CollectionResult.Result.SUCCESSFUL);
}catch(Exception ex){
if(logErrors)
error("An error occured during collect callback for PingCollector: "+this.getBeanName(),ex);
result.setResultForLastCollection(CollectionResult.Result.FAILURE);
result.setAnyException(ex);
return result;
}finally{
tracer.traceGauge(System.currentTimeMillis()-start, "Elapsed Time", "Collectors", getClass().getSimpleName());
}
return result;
}
/**
* Returns the Ping Collector version
*/
public String getCollectorVersion() {
return "PingCollector v. " + PING_COLLECTOR_VERSION;
}
/**
* Performs any tasks that are necessary before the Ping collector can be started
*/
public void startCollector() throws CollectorException {
isWindows = System.getProperty("os.name").toUpperCase().contains("WINDOWS");
}
/**
* Issues an OS Ping to the specified address.
* @param ipAddress The IP Address to ping.
* @return A string representing the native ping request output.
*/
public String ping(String ipAddress) throws Exception{
long start = System.currentTimeMillis();
StringBuilder buff = new StringBuilder();
InputStream reader = null;
try {
ProcessBuilder pb = null;
if(isWindows) {
pb = new ProcessBuilder("ping.exe", "-n", "" + packetCount, "-l", "" + packetSize, "-w", "" + (timeout*1000), ipAddress);
} else {
pb = new ProcessBuilder("/bin/ping", "-c", "" + packetCount, "-s", "" + packetSize, "-W", "" + timeout, ipAddress);
}
Process p = pb.start();
reader = new BufferedInputStream(p.getInputStream());
for (;;) {
int c = reader.read();
if (c == -1)
break;
buff.append((char) c);
}
info("ping took: "+ (System.currentTimeMillis() - start));
return buff.toString();
}finally {
try { reader.close(); } catch (Exception e) {debug(e.getMessage());}
}
}
/**
* Processes the output of a Windows Ping
* @param output The output of the ping command
* @param hostName The hostName that was pinged.
*/
public void processWindowsPing(String output, String hostName) {
StringReader reader = new StringReader(output);
BufferedReader br = new BufferedReader(reader);
String line = null;
try {
while((line=br.readLine().trim())!=null) {
if(line.startsWith("Minimum")) {
String readings[] = line.split(",");
for(String reading: readings) {
try {
String readingFragments[] = reading.replaceAll("\\s+", "").split("=");
String timeType = readingFragments[0];
long value = Long.parseLong(readingFragments[1].substring(0, readingFragments[1].indexOf("ms")));
tracer.traceGauge(value, timeType, "Collectors", getClass().getSimpleName(), "os=windows","host="+hostName);
} catch (Exception e) {debug(e.getMessage());}
}
} else if(line.startsWith("Packets:")) {
try {
int value = Integer.parseInt(line.split("\\(")[1].split("\\)")[0].split("%")[0]);
tracer.traceGauge(value, "Packet Loss", "Collectors", getClass().getSimpleName(), "os=windows","host="+hostName);
if(value==100) {
tracer.traceGauge(-1, "Minimum", "Collectors", getClass().getSimpleName(), "os=windows","host="+hostName);
tracer.traceGauge(-1, "Maximum", "Collectors", getClass().getSimpleName(), "os=windows","host="+hostName);
tracer.traceGauge(-1, "Average", "Collectors", getClass().getSimpleName(), "os=windows","host="+hostName);
}
} catch (Exception e) {}
}
}
} catch (Exception e) {
// Noop
}
}
/**
* Processes the output of a Linux Ping
* @param output The output of the ping command
* @param hostName The hostName that was pinged.
*/
public void processLinuxPing(String output, String hostName) {
StringReader reader = new StringReader(output);
BufferedReader br = new BufferedReader(reader);
String line = null;
try {
while((line=br.readLine())!=null) {
line = line.trim();
if(line.startsWith("rtt")) {
String readings[] = line.split(" = ");
String[] values = readings[1].split("/");
long value = 0L;
try {
value = (long)Float.parseFloat(values[0]);
tracer.traceGauge(value, "Minimum", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
} catch (Exception e) {debug(e.getMessage());}
try {
value = (long)Float.parseFloat(values[1]);
tracer.traceGauge(value, "Average", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
} catch (Exception e) {}
try {
value = (long)Float.parseFloat(values[2]);
tracer.traceGauge(value, "Maximum", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
} catch (Exception e) {}
} else if(line.contains("packets transmitted")) {
try {
int value = Integer.parseInt(line.split(",")[2].trim().split("\\s+")[0].replaceAll("%",""));
tracer.traceGauge(value, "Packet Loss", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
if(value==100) {
tracer.traceGauge(-1, "Minimum", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
tracer.traceGauge(-1, "Maximum", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
tracer.traceGauge(-1, "Average", "Collectors", getClass().getSimpleName(), "os=linux","host="+hostName);
}
} catch (Exception e) {}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @return the servers
*/
public List<String> getServers() {
return servers;
}
/**
* @param servers the servers to set
*/
public void setServers(List<String> servers) {
this.servers = servers;
}
/**
* @return the packetSize
*/
public int getPacketSize() {
return packetSize;
}
/**
* @param packetSize the packetSize to set
*/
public void setPacketSize(int packetSize) {
this.packetSize = packetSize;
}
/**
* @return the packetCount
*/
public int getPacketCount() {
return packetCount;
}
/**
* @param packetCount the packetCount to set
*/
public void setPacketCount(int packetCount) {
this.packetCount = packetCount;
}
/**
* @return the timeout
*/
public int getTimeout() {
return timeout;
}
/**
* @param timeout the timeout to set
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
/**
* Display a list of servers monitored by this collector.
* @return A string report.
*/
@ManagedOperation
public String reportServers() {
StringBuilder buff = new StringBuilder();
for(String s: servers) {
String[] fragment = s.split("\\|");
buff.append("IP Address:").append(fragment[0].trim()).append("\n");
buff.append("Host Name:").append(fragment[1].trim()).append("\n");
buff.append("===============================================\n");
}
return buff.toString();
}
}