package com.ibm.nmon.parser; import org.slf4j.Logger; import java.io.File; import java.io.IOException; import java.io.LineNumberReader; import java.util.regex.Pattern; import com.ibm.nmon.data.BasicDataSet; import com.ibm.nmon.data.DataType; import com.ibm.nmon.data.DataRecord; import com.ibm.nmon.util.DataHelper; public final class HATJParser { private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(NMONParser.class); private static final Pattern DATA_SPLITTER = Pattern.compile(","); public static final String DEFAULT_HOSTNAME = "hatj"; public BasicDataSet parse(File file) throws IOException { return parse(file.getAbsolutePath()); } public BasicDataSet parse(String filename) throws IOException { long start = System.nanoTime(); // assume HATJ file is like graph<timeinmillis>_<testname>.csv; testname is optional int graphIdx = filename.indexOf("graph"); if (graphIdx == -1) { LOGGER.error("HATJ file name '{}' does not start with 'graph'", filename); return null; } int idx = filename.indexOf("_", graphIdx); int end = filename.length() - ".csv".length(); String hostname = DEFAULT_HOSTNAME; if (idx == -1) { idx = end; // time is the rest of the string // hostname stays default } else { // time is up to the first _ hostname = filename.substring(idx + 1, end); } String temp = filename.substring(graphIdx + "graph".length(), idx); long startTime = 0; try { startTime = Long.parseLong(temp); } catch (NumberFormatException nfe) { LOGGER.warn("no valid start time in the file name, using the current time", filename); startTime = System.currentTimeMillis(); } LineNumberReader in = null; try { in = new LineNumberReader(new java.io.FileReader(filename)); String line = in.readLine(); if (line == null) { throw new IOException("file '" + filename + "' does not appear to have any data records"); } BasicDataSet data = new BasicDataSet(filename); data.setHostname(hostname); // create DataTypes from header line String[] values = DATA_SPLITTER.split(line); // data[0] = Duration; data[1] = Throughput; data[2] = Hits/sec; data[3] = # of Users String[] fields = new String[values.length - 4]; // transaction names are like package.name.Class (optional TX name) // shorten the package name to just the first letter and remove spaces from the TX name // so the legend will be a little smaller on charts for (int i = 0; i < fields.length; i++) { String raw = values[i + 4]; idx = raw.indexOf('.'); int lastDot = -1; StringBuilder txName = new StringBuilder(64); txName.append(raw.charAt(0)).append('.'); while (idx != -1) { txName.append(raw.charAt(++idx)).append('.'); lastDot = idx; idx = raw.indexOf('.', idx); } // remove extra . txName.deleteCharAt(txName.length() - 1); // find optional TX name ++lastDot; idx = raw.indexOf('(', lastDot); if (idx == -1) { // just add the rest of the package name txName.append(raw.substring(lastDot)); } else { // add the rest of the package name... txName.append(raw.substring(lastDot, idx)); // remove spaces from TX name for (int j = idx; j < raw.length(); j++) { if (raw.charAt(j) != ' ') { txName.append(raw.charAt(j)); } } } fields[i] = txName.toString(); } DataType info = new DataType("INFO", "HATJ Test Information", "throughput", "hits", "users"); DataType response = new DataType("RESP", "HATJ Response Times", fields); data.addType(info); data.addType(response); while ((line = in.readLine()) != null) { values = DATA_SPLITTER.split(line); long duration = Long.parseLong(values[0]); DataRecord record = new DataRecord(startTime + (duration * 1000), DataHelper.newString(values[0])); record.addData(info, new double[] { Double.parseDouble(values[1]), Double.parseDouble(values[2]), Double.parseDouble(values[3]) }); double[] recordData = new double[response.getFieldCount()]; int n = 0; for (int i = 4; i < values.length; i++) { if ("".equals(values[i]) || values[i].contains("nan")) { recordData[n] = Double.NaN; } else { recordData[n] = Double.parseDouble(values[i]); } ++n; } record.addData(response, recordData); data.addRecord(record); } return data; } finally { if (in != null) { try { in.close(); } catch (Exception e) { // ignore } in = null; } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parse complete for {} in {}ms", filename, (System.nanoTime() - start) / 1000000.0d); } } } }