From d3db8adcb0d68b4e1ae42e8c5e888f813e8ef078 Mon Sep 17 00:00:00 2001 From: Samuel Mendenhall Date: Mon, 9 Jun 2014 15:53:48 -0400 Subject: [PATCH 1/2] Adding the ability to specify the type of output to a file while maintaining backwards compatibility with the current options. Also allowing a new output type CSV_TS which prefers the unix timestamp of the entry first. --- .../com/tagtraum/perf/gcviewer/GCViewer.java | 72 +++++++++++++---- .../perf/gcviewer/exp/DataWriterType.java | 1 + .../gcviewer/exp/impl/CSVTSDataWriter.java | 56 +++++++++++++ .../gcviewer/exp/impl/DataWriterFactory.java | 1 + .../com/tagtraum/perf/gcviewer/TestAll.java | 1 + .../tagtraum/perf/gcviewer/TestGCViewer.java | 80 +++++++++++++++++++ 6 files changed, 196 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java create mode 100644 src/test/java/com/tagtraum/perf/gcviewer/TestGCViewer.java diff --git a/src/main/java/com/tagtraum/perf/gcviewer/GCViewer.java b/src/main/java/com/tagtraum/perf/gcviewer/GCViewer.java index 84fe012b..804f612f 100755 --- a/src/main/java/com/tagtraum/perf/gcviewer/GCViewer.java +++ b/src/main/java/com/tagtraum/perf/gcviewer/GCViewer.java @@ -9,53 +9,94 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; public class GCViewer { private static final Logger LOGGER = Logger.getLogger(GCViewer.class.getName()); - public static void main(final String[] args) { - if (args.length > 3) { + // Default to the summary type + private String type = "SUMMARY"; + public String getType() { return type; } + public void setType(String type) { this.type = type; } + + // receives other command line parameters than options + private List arguments = new ArrayList(); + public List getArguments() { return arguments; } + public void setArguments(List arguments) { this.arguments = arguments; } + + public static void main(final String[] args) throws IOException { + new GCViewer().doMain(args); + } + + public void parseArguments(String[] args) { + List argsList = new ArrayList(Arrays.asList(args)); + int typeIdx = argsList.indexOf("-t"); + + // If there is a -t and there is a string after, set the type + if(typeIdx != -1 && argsList.size() > (typeIdx + 1)) { + type = argsList.get(typeIdx + 1); + // Chomp these two from the array to prevent any order issues + argsList.remove(typeIdx); + argsList.remove(typeIdx); + } else if (typeIdx != -1) { + // No specific type set, just keep the default + argsList.remove(typeIdx); + } + + // Set the arguments to the remaining arguments + arguments = argsList; + } + + public void doMain(String[] args) throws IOException { + parseArguments(args); + + if (arguments.size() > 3) { usage(); } - else if (args.length >= 2) { - final String gcfile = args[0]; - final String summaryFilePath = args[1]; - final String chartFilePath = args.length == 3 ? args[2] : null; + else if (arguments.size() >= 2) { + final String gcfile = arguments.get(0); + final String summaryFilePath = arguments.get(1); + final String chartFilePath = arguments.size() == 3 ? arguments.get(2) : null; //export summary: try { export(gcfile, summaryFilePath, chartFilePath); System.exit(0); - } - catch(Exception e) { + } catch(IllegalArgumentException e) { + LOGGER.log(Level.SEVERE, "Type must be one of SUMMARY, CSV, CSV_TS, PLAIN, SIMPLE", e); + System.exit(-1); + } catch(Exception e) { LOGGER.log(Level.SEVERE, "Error during report generation", e); System.exit(-1); } } else { - GCViewerGui.start(args.length == 1 ? args[0] : null); + GCViewerGui.start(arguments.size() == 1 ? arguments.get(0) : null); } } - private static void export(String gcFilename, String summaryFilePath, String chartFilePath) - throws IOException, DataReaderException { + private void export(String gcFilename, String summaryFilePath, String chartFilePath) + throws IOException, DataReaderException, IllegalArgumentException { DataReaderFacade dataReaderFacade = new DataReaderFacade(); GCModel model = dataReaderFacade.loadModel(gcFilename, false, null); + DataWriterType dataWriterType = DataWriterType.valueOf(type.trim().toUpperCase()); - exportSummary(model, summaryFilePath); + exportType(model, summaryFilePath, dataWriterType); if (chartFilePath != null) renderChart(model, chartFilePath); } - private static void exportSummary(GCModel model, String summaryFilePath) throws IOException { - try (DataWriter summaryWriter = DataWriterFactory.getDataWriter(new File(summaryFilePath), DataWriterType.SUMMARY)) { + private void exportType(GCModel model, String summaryFilePath, DataWriterType type) throws IOException { + try (DataWriter summaryWriter = DataWriterFactory.getDataWriter(new File(summaryFilePath), type)) { summaryWriter.write(model); } } - private static void renderChart(GCModel model, String chartFilePath) throws IOException { + private void renderChart(GCModel model, String chartFilePath) throws IOException { SimpleChartRenderer renderer = new SimpleChartRenderer(); renderer.render(model, chartFilePath); } @@ -66,6 +107,7 @@ private static void usage() { System.out.println("java -jar gcviewer.jar [] [] -> cmdline: writes report to "); System.out.println("java -jar gcviewer.jar [] [] [] " + "-> cmdline: writes report to and renders gc chart to "); + System.out.println("java -jar gcviewer.jar [] [] [] [-t ]"); } } diff --git a/src/main/java/com/tagtraum/perf/gcviewer/exp/DataWriterType.java b/src/main/java/com/tagtraum/perf/gcviewer/exp/DataWriterType.java index bf87ba86..85caaf5b 100644 --- a/src/main/java/com/tagtraum/perf/gcviewer/exp/DataWriterType.java +++ b/src/main/java/com/tagtraum/perf/gcviewer/exp/DataWriterType.java @@ -9,6 +9,7 @@ public enum DataWriterType { PLAIN, CSV, + CSV_TS, SIMPLE, SUMMARY; } diff --git a/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java b/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java new file mode 100644 index 00000000..111bbcc2 --- /dev/null +++ b/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java @@ -0,0 +1,56 @@ +package com.tagtraum.perf.gcviewer.exp.impl; + +import com.tagtraum.perf.gcviewer.exp.AbstractDataWriter; +import com.tagtraum.perf.gcviewer.model.GCEvent; +import com.tagtraum.perf.gcviewer.model.GCModel; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; + +/** + * + * Date: Feb 1, 2002 + * Time: 10:07:52 AM + * @author Hendrik Schreiber + */ +public class CSVTSDataWriter extends AbstractDataWriter { + + public CSVTSDataWriter(OutputStream out) { + super(out); + } + + private void writeHeader() { + out.println("Timestamp(unix/#),Used(K),Total(K),Pause(sec),GC-Type"); + } + + /** + * Writes the model and flushes the internal PrintWriter. + */ + public void write(GCModel model) throws IOException { + writeHeader(); + + Iterator i = model.getGCEvents(); + while (i.hasNext()) { + GCEvent event = i.next(); + // Since this data writer is only concerned with one line per gc entry, don't write two like the others. + + // If the true timestamp is present, output the unix timestamp + if (model.hasCorrectTimestamp()) { + out.print(event.getDatestamp().getTime()); + } else { + out.print(event.getTimestamp()); + } + out.print(','); + out.print(event.getPreUsed()); // pre + out.print(','); + out.print(event.getTotal()); + out.print(','); + out.print(event.getPause()); + out.print(','); + out.println(event.getExtendedType()); + } + out.flush(); + } + +} diff --git a/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/DataWriterFactory.java b/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/DataWriterFactory.java index 33845255..6939fe3f 100644 --- a/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/DataWriterFactory.java +++ b/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/DataWriterFactory.java @@ -50,6 +50,7 @@ public static DataWriter getDataWriter(File file, DataWriterType type, MapSamuel Mendenhall + *

created on: 06.09.2014

+ */ +public class TestGCViewer { + + @Test + public void noArguments() throws IOException { + String[] args = {}; + GCViewer gcViewer = new GCViewer(); + gcViewer.parseArguments(args); + + assertEquals(gcViewer.getArguments().size(), 0); + assertEquals(gcViewer.getType(), "SUMMARY"); + +// assertNotNull("version", version); +// assertFalse("must not be n/a", version.equals("n/a")); + } + + @Test + public void onlyGCLog() throws IOException { + String[] args = {"some_gc.log"}; + GCViewer gcViewer = new GCViewer(); + gcViewer.parseArguments(args); + + assertEquals(gcViewer.getArguments().size(), 1); + assertEquals(gcViewer.getArguments().get(0), "some_gc.log"); + assertEquals(gcViewer.getType(), "SUMMARY"); + } + + @Test + public void gcAndExportFile() throws IOException { + String[] args = {"some_gc.log", "export_to.csv"}; + GCViewer gcViewer = new GCViewer(); + gcViewer.parseArguments(args); + + assertEquals(gcViewer.getArguments().size(), 2); + assertEquals(gcViewer.getArguments().get(0), "some_gc.log"); + assertEquals(gcViewer.getArguments().get(1), "export_to.csv"); + assertEquals(gcViewer.getType(), "SUMMARY"); + } + + @Test + public void onlyType() throws IOException { + String[] args = {"-t", "CSV_TS"}; + GCViewer gcViewer = new GCViewer(); + gcViewer.parseArguments(args); + + assertEquals(gcViewer.getArguments().size(), 0); + assertEquals(gcViewer.getType(), "CSV_TS"); + } + + @Test + public void allInitialArgsWithType() throws IOException { + String[] args = {"some_gc.log", "export_to.csv", "the_chart.png", "-t", "CSV"}; + GCViewer gcViewer = new GCViewer(); + gcViewer.parseArguments(args); + + assertEquals(gcViewer.getArguments().size(), 3); + assertEquals(gcViewer.getArguments().get(0), "some_gc.log"); + assertEquals(gcViewer.getArguments().get(1), "export_to.csv"); + assertEquals(gcViewer.getArguments().get(2), "the_chart.png"); + assertEquals(gcViewer.getType(), "CSV"); + } +} From fd9b977b181311b1f91d464d20b15471a2bc9af3 Mon Sep 17 00:00:00 2001 From: Samuel Mendenhall Date: Mon, 9 Jun 2014 17:13:00 -0400 Subject: [PATCH 2/2] Gracefully failing to the non-unix time if datestamp not available --- .../com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java b/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java index 111bbcc2..a1987c10 100644 --- a/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java +++ b/src/main/java/com/tagtraum/perf/gcviewer/exp/impl/CSVTSDataWriter.java @@ -36,8 +36,11 @@ public void write(GCModel model) throws IOException { // Since this data writer is only concerned with one line per gc entry, don't write two like the others. // If the true timestamp is present, output the unix timestamp - if (model.hasCorrectTimestamp()) { + if (model.hasDateStamp()) { out.print(event.getDatestamp().getTime()); + } else if (model.hasCorrectTimestamp()) { + // we have the timestamps therefore we can correct it with the pause time + out.print((event.getTimestamp() - event.getPause())); } else { out.print(event.getTimestamp()); }