Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.mgmtp.perfload.perfmon.PerfMon Maven / Gradle / Ivy
/*
* Copyright (c) 2013 mgm technology partners GmbH
*
* Licensed 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.mgmtp.perfload.perfmon;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.lang.text.StrBuilder;
import org.apache.commons.lang.time.FastDateFormat;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.SigarProxy;
import org.hyperic.sigar.SigarProxyCache;
import org.hyperic.sigar.cmd.Shell;
import org.hyperic.sigar.cmd.Uptime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mgmtp.perfload.perfmon.cmd.BasePerfMonCommand;
import com.mgmtp.perfload.perfmon.cmd.PerfMonCpu;
import com.mgmtp.perfload.perfmon.cmd.PerfMonIo;
import com.mgmtp.perfload.perfmon.cmd.PerfMonJava;
import com.mgmtp.perfload.perfmon.cmd.PerfMonMem;
import com.mgmtp.perfload.perfmon.cmd.PerfMonNetStat;
import com.mgmtp.perfload.perfmon.cmd.PerfMonProc;
import com.mgmtp.perfload.perfmon.cmd.PerfMonSwap;
import com.mgmtp.perfload.perfmon.cmd.PerfMonTcp;
import com.mgmtp.perfload.perfmon.io.ConsoleOutputHandler;
import com.mgmtp.perfload.perfmon.io.FileOutputHandler;
import com.mgmtp.perfload.perfmon.io.OutputHandler;
import com.mgmtp.perfload.perfmon.util.PerfMonUtils;
/**
* Utility program for logging system information using Sigar .
*
* @author rnaegele
*/
class PerfMon {
private static final Logger LOG = LoggerFactory.getLogger(PerfMon.class);
private static final String SEPARATOR = "\t";
private static final Pattern LINE_PATTERN = Pattern.compile("^(.*)$", Pattern.MULTILINE);
private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
private final long interval;
private final boolean csv;
private final List commands;
private final OutputHandler outputHandler;
private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
// It is important to use SigarProxyCache and to reuse the instance in order to avoid CPU spikes.
final SigarProxy sigar = SigarProxyCache.newInstance(new Sigar());
PerfMon(final long interval, final boolean csv, final List commands,
final OutputHandler outputHandler) {
this.interval = interval;
this.csv = csv;
this.commands = commands;
this.outputHandler = outputHandler;
}
void writeHeader() {
String hostName = PerfMonUtils.getHostName();
StringBuilder metaBuffer = new StringBuilder(200);
metaBuffer.append(DATE_FORMAT.format(System.currentTimeMillis()));
metaBuffer.append(SEPARATOR);
metaBuffer.append("meta");
metaBuffer.append(SEPARATOR);
metaBuffer.append("perfMon ").append(PerfMonUtils.getPerfMonVersion());
metaBuffer.append(SEPARATOR);
metaBuffer.append(hostName);
LOG.info("Hostname: {}", hostName);
try {
LOG.info("CPUs: {}", sigar.getCpuList().length);
LOG.info("Total RAM: {} MB", sigar.getMem().getRam());
LOG.info("Uptime: {}", Uptime.getInfo(sigar));
} catch (SigarException ex) {
LOG.error("Error retrieving system information from Sigar.", ex);
}
try {
InetAddress[] networkIPAddresses = PerfMonUtils.getNetworkIPAddresses();
if (networkIPAddresses.length > 0) {
LOG.info("Local IP addresses:");
metaBuffer.append(SEPARATOR);
for (int i = 0; i < networkIPAddresses.length; ++i) {
InetAddress ip = networkIPAddresses[i];
if (i > 0) {
metaBuffer.append(',');
}
metaBuffer.append(ip);
LOG.info(ip.toString());
}
}
} catch (UnknownHostException ex) {
LOG.error("Error retrieving IP addresses of the localhost.", ex);
}
try {
LOG.info("Full list of network interfaces:");
List networkInterfaces = PerfMonUtils.getNetworkInterfaces();
for (NetworkInterface ni : networkInterfaces) {
for (Enumeration en = ni.getInetAddresses(); en.hasMoreElements();) {
LOG.info("\t\t{}", en.nextElement().toString());
}
}
} catch (SocketException ex) {
LOG.error("Error retrieving network interfaces.", ex);
}
if (csv) {
StrBuilder sb = new StrBuilder(200);
sb.append("timestamp");
for (BasePerfMonCommand cmd : commands) {
sb.append(SEPARATOR);
String header = cmd.getCsvHeader();
sb.append(header);
}
outputHandler.writeln(sb.toString());
} else {
outputHandler.writeln(metaBuffer.toString());
}
}
void scheduleInformationGathering() {
executor.scheduleAtFixedRate(new Runnable() {
public void run() {
try {
StrBuilder buffer = new StrBuilder(2000);
for (BasePerfMonCommand cmd : commands) {
buffer.appendSeparator(csv ? SEPARATOR : PerfMonUtils.LINE_SEP);
buffer.append(cmd.executeCommand(sigar));
}
String output = buffer.toString();
// insert timestamp at the beginning of each line
String isoTimestamp = DATE_FORMAT.format(System.currentTimeMillis());
output = LINE_PATTERN.matcher(output).replaceAll(isoTimestamp + SEPARATOR + "$1");
outputHandler.writeln(output);
} catch (Exception ex) {
LOG.error(ex.getMessage(), ex);
}
}
}, 0L, interval, TimeUnit.SECONDS);
}
void runShutdownHook() {
try {
LOG.info("Running shutdown hook...");
executor.shutdownNow();
executor.awaitTermination(interval, TimeUnit.SECONDS);
outputHandler.close();
LOG.info("Good bye.");
} catch (InterruptedException ex) {
// ignore
}
}
public static void main(final String[] args) {
CommandLine cmd = parseArgs(args);
if (cmd != null) {
if (cmd.hasOption('s')) {
shutdown();
return;
}
long interval = Long.parseLong(cmd.getOptionValue('i', "5"));
String fileName = cmd.getOptionValue('f');
boolean csv = cmd.hasOption('c');
boolean java = cmd.hasOption('j');
boolean tcp = cmd.hasOption('t');
boolean normalizeTcp = cmd.hasOption("tn");
boolean netstat = cmd.hasOption('n');
boolean normalizeIo = cmd.hasOption("in");
OutputHandler outputHandler = fileName != null ? new FileOutputHandler(fileName) : new ConsoleOutputHandler();
try {
outputHandler.open();
List commands = createCommandsList(csv, java, tcp, normalizeTcp, netstat, normalizeIo);
final PerfMon perfMon = new PerfMon(interval, csv, commands, outputHandler);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
perfMon.runShutdownHook();
}
});
perfMon.writeHeader();
perfMon.scheduleInformationGathering();
} catch (IOException ex) {
LOG.error("Error opening output file: " + fileName, ex);
}
}
}
static void shutdown() {
LOG.info("Shutting down perfMon...");
Sigar sigar = new Sigar();
String[] type = new String[] { "State.Name.sw=java,Args.*.re=perf(m|M)on" };
try {
long ownPid = sigar.getPid();
long[] pids = Shell.getPids(sigar, type);
for (long pid : pids) {
if (pid != ownPid) {
LOG.info("Sending SIGTERM signal to perfMon process with PID {}", pid);
sigar.kill(pid, "TERM");
}
}
} catch (SigarException ex) {
LOG.error(ex.getMessage(), ex);
}
}
static List createCommandsList(final boolean csv, final boolean java, final boolean tcp,
final boolean normalizeTcp, final boolean netStat, final boolean normalizeIo) {
List commands = new ArrayList();
commands.add(new PerfMonCpu(SEPARATOR, csv));
commands.add(new PerfMonMem(SEPARATOR, csv));
commands.add(new PerfMonSwap(SEPARATOR, csv));
if (tcp) {
commands.add(new PerfMonTcp(SEPARATOR, csv, normalizeTcp));
}
if (netStat) {
commands.add(new PerfMonNetStat(SEPARATOR, csv));
}
commands.add(new PerfMonIo(SEPARATOR, csv, normalizeIo));
commands.add(new PerfMonProc(SEPARATOR, csv));
if (java) {
commands.add(new PerfMonJava(SEPARATOR, csv));
}
return commands;
}
static CommandLine parseArgs(final String[] args) {
Options options = new Options();
try {
Option option = new Option("i", "interval", true, "The interval for printing the system information (default 5 sec).");
option.setArgName("SECONDS");
options.addOption(option);
option = new Option("f", "file", true,
"The output file the information is written to. Stdout is used if no file is specified.");
option.setArgName("FILE");
options.addOption(option);
options.addOption("c", "csv", false, "Write all data in one line for easier import in tools such as Excel.");
options.addOption("j", "java", false, "Write information on Java processes.");
options.addOption("t", "tcp", false, "Write TCP connection information.");
options.addOption("tn", "normalize-tcp", false, "Normalize TCP connection information against an initial offset.");
options.addOption("n", "netstat", false, "Write network statistics");
options.addOption("in", "normalize-io", false, "Normalize IO information against an initial offset.");
options.addOption("s", "shutdown", false, "Shutdown all running perfMon processes on this machine.");
options.addOption("h", "help", false, "Prints usage information.");
CommandLineParser parser = new PosixParser();
CommandLine cmd = parser.parse(options, args);
if (!cmd.hasOption('h')) {
return cmd;
}
} catch (ParseException ex) {
LOG.error(ex.getMessage(), ex);
}
printUsage(options);
return null;
}
static void printUsage(final Options options) {
HelpFormatter help = new HelpFormatter();
help.printHelp("perfMon", options);
}
}