Skip to content

Commit ef9695b

Browse files
committed
Merge branch 'feature/#61' into develop
# Conflicts: # src/main/java/com/tagtraum/perf/gcviewer/ctrl/impl/GCModelLoaderControllerImpl.java # src/main/java/com/tagtraum/perf/gcviewer/ctrl/impl/GCViewerGuiBuilder.java # src/main/java/com/tagtraum/perf/gcviewer/ctrl/impl/GCViewerGuiController.java
2 parents 89bf7bf + 536ba64 commit ef9695b

File tree

89 files changed

+3857
-1029
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+3857
-1029
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ is free software released under GNU LGPL.
1111
You can start GCViewer (gui) by simply double-clicking on gcviewer-1.3x.jar
1212
or running java -jar gcviewer-1.3x.jar (it needs a java 1.8 vm to run).
1313

14-
For a cmdline based report summary just type:
15-
java -jar gcviewer-1.3x.jar gc.log summary.csv [chart.png] [-t PLAIN|CSV|CSV_TS|SIMPLE|SUMMARY]
16-
17-
to generate a report (including optional chart image file).
14+
For a cmdline based report summary just type the following to generate a report (including optional chart image file):
15+
`java -jar gcviewer-1.3x.jar gc.log summary.csv [chart.png] [-t PLAIN|CSV|CSV_TS|SIMPLE|SUMMARY]`
16+
When logfile rotation (-XX:+UseGCLogFileRotation) is enabled, the logfiles can be read at once:
17+
`java -jar gcviewer-1.3x.jar gc.log.0;gc.log.1;gc.log.2;gc.log.current summary.csv [chart.png] [-t PLAIN|CSV|CSV_TS|SIMPLE|SUMMARY]`
1818

1919

2020
Supported verbose:gc formats are:
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
package com.tagtraum.perf.gcviewer;
22

3-
import java.io.File;
4-
import java.io.FileOutputStream;
5-
import java.io.IOException;
6-
import java.lang.reflect.InvocationTargetException;
7-
import java.util.logging.Level;
8-
import java.util.logging.Logger;
9-
103
import com.tagtraum.perf.gcviewer.ctrl.impl.GCViewerGuiController;
114
import com.tagtraum.perf.gcviewer.exp.DataWriter;
125
import com.tagtraum.perf.gcviewer.exp.DataWriterType;
@@ -17,6 +10,13 @@
1710
import com.tagtraum.perf.gcviewer.model.GCResource;
1811
import com.tagtraum.perf.gcviewer.view.SimpleChartRenderer;
1912

13+
import java.io.File;
14+
import java.io.FileOutputStream;
15+
import java.io.IOException;
16+
import java.lang.reflect.InvocationTargetException;
17+
import java.util.logging.Level;
18+
import java.util.logging.Logger;
19+
2020
/**
2121
* Main class of GCViewer. Parses command line parameters if there are any and either remains
2222
* in command line mode or starts the gui (depending on parameters).
@@ -26,13 +26,24 @@ public class GCViewer {
2626
private static final int EXIT_OK = 0;
2727
private static final int EXIT_EXPORT_FAILED = -1;
2828
private static final int EXIT_ARGS_PARSE_FAILED = -2;
29+
private GCViewerGuiController gcViewerGuiController;
30+
private GCViewerArgsParser gcViewerArgsParser;
31+
32+
public GCViewer() {
33+
this(new GCViewerGuiController(), new GCViewerArgsParser());
34+
}
35+
36+
public GCViewer(GCViewerGuiController gcViewerGuiController, GCViewerArgsParser gcViewerArgsParser) {
37+
this.gcViewerGuiController = gcViewerGuiController;
38+
this.gcViewerArgsParser = gcViewerArgsParser;
39+
}
2940

30-
public static void main(final String[] args) throws InvocationTargetException, InterruptedException {
41+
public static void main(final String[] args) throws InvocationTargetException, InterruptedException {
3142
new GCViewer().doMain(args);
3243
}
3344

3445
public void doMain(String[] args) throws InvocationTargetException, InterruptedException {
35-
GCViewerArgsParser argsParser = new GCViewerArgsParser();
46+
GCViewerArgsParser argsParser = gcViewerArgsParser;
3647
try {
3748
argsParser.parseArguments(args);
3849
}
@@ -47,14 +58,14 @@ public void doMain(String[] args) throws InvocationTargetException, InterruptedE
4758
}
4859
else if (argsParser.getArgumentCount() >= 2) {
4960
LOGGER.info("GCViewer command line mode");
50-
String gcfile = argsParser.getGcfile();
61+
GCResource gcResource = argsParser.getGcResource();
5162
String summaryFilePath = argsParser.getSummaryFilePath();
5263
String chartFilePath = argsParser.getChartFilePath();
5364
DataWriterType type = argsParser.getType();
5465

5566
//export summary:
5667
try {
57-
export(gcfile, summaryFilePath, chartFilePath, type);
68+
export(gcResource, summaryFilePath, chartFilePath, type);
5869
LOGGER.info("export completed successfully");
5970
System.exit(EXIT_OK);
6071
}
@@ -64,22 +75,22 @@ else if (argsParser.getArgumentCount() >= 2) {
6475
}
6576
}
6677
else {
67-
new GCViewerGuiController().startGui(argsParser.getArgumentCount() == 1 ? argsParser.getGcfile() : null);
78+
gcViewerGuiController.startGui(argsParser.getArgumentCount() == 1 ? argsParser.getGcResource() : null);
6879
}
6980
}
7081

71-
private void export(String gcFilename, String summaryFilePath, String chartFilePath, DataWriterType type)
82+
private void export(GCResource gcResource, String summaryFilePath, String chartFilePath, DataWriterType type)
7283
throws IOException, DataReaderException {
7384

7485
DataReaderFacade dataReaderFacade = new DataReaderFacade();
75-
GCModel model = dataReaderFacade.loadModel(new GCResource(gcFilename));
86+
GCModel model = dataReaderFacade.loadModel(gcResource);
7687

7788
exportType(model, summaryFilePath, type);
7889
if (chartFilePath != null)
7990
renderChart(model, chartFilePath);
8091
}
8192

82-
private void exportType(GCModel model, String summaryFilePath, DataWriterType type) throws IOException {
93+
private void exportType(GCModel model, String summaryFilePath, DataWriterType type) throws IOException {
8394
try (DataWriter summaryWriter = DataWriterFactory.getDataWriter(new File(summaryFilePath), type)) {
8495
summaryWriter.write(model);
8596
}
@@ -90,13 +101,16 @@ private void renderChart(GCModel model, String chartFilePath) throws IOException
90101
renderer.render(model, new FileOutputStream(new File(chartFilePath)));
91102
}
92103

93-
private static void usage() {
94-
System.out.println("Welcome to GCViewer with cmdline");
104+
private static void usage() {
105+
System.out.println("Welcome to GCViewer with cmdline");
95106
System.out.println("java -jar gcviewer.jar [<gc-log-file|url>] -> opens gui and loads given file");
107+
System.out.println("java -jar gcviewer.jar [<gc-log-file|url>];[<gc-log-file|url>];[...] -> opens gui and loads given files as series of rotated logfiles");
96108
System.out.println("java -jar gcviewer.jar [<gc-log-file>] [<export.csv>] -> cmdline: writes report to <export.csv>");
97-
System.out.println("java -jar gcviewer.jar [<gc-log-file>] [<export.csv>] [<chart.png>] " +
98-
"-> cmdline: writes report to <export.csv> and renders gc chart to <chart.png>");
99-
System.out.println("java -jar gcviewer.jar [<gc-log-file>] [<export.csv>] [<chart.png>] [-t <SUMMARY, CSV, CSV_TS, PLAIN, SIMPLE>]");
109+
System.out.println("java -jar gcviewer.jar [<gc-log-file|url>];[<gc-log-file|url>];[...] [<export.csv>] -> cmdline: loads given files as series of rotated logfiles and writes report to <export.csv>");
110+
System.out.println("java -jar gcviewer.jar [<gc-log-file>] [<export.csv>] [<chart.png>] -> cmdline: writes report to <export.csv> and renders gc chart to <chart.png>");
111+
System.out.println("java -jar gcviewer.jar [<gc-log-file|url>];[<gc-log-file|url>];[...] [<export.csv>] [<chart.png>] -> cmdline: loads given files as series of rotated logfiles and writes report to <export.csv> and renders gc chart to <chart.png>");
112+
System.out.println("java -jar gcviewer.jar [<gc-log-file|url>] [<export.csv>] [<chart.png>] [-t <SUMMARY, CSV, CSV_TS, PLAIN, SIMPLE>]");
113+
System.out.println("java -jar gcviewer.jar [<gc-log-file|url>];[<gc-log-file|url>];[...] [<export.csv>] [<chart.png>] [-t <SUMMARY, CSV, CSV_TS, PLAIN, SIMPLE>]");
100114
}
101115

102116
}

src/main/java/com/tagtraum/perf/gcviewer/GCViewerArgsParser.java

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package com.tagtraum.perf.gcviewer;
22

3+
import com.tagtraum.perf.gcviewer.exp.DataWriterType;
4+
import com.tagtraum.perf.gcviewer.model.GCResource;
5+
import com.tagtraum.perf.gcviewer.model.GcResourceFile;
6+
import com.tagtraum.perf.gcviewer.model.GcResourceSeries;
7+
38
import java.util.ArrayList;
49
import java.util.Arrays;
510
import java.util.List;
6-
7-
import com.tagtraum.perf.gcviewer.exp.DataWriterType;
11+
import java.util.stream.Collectors;
812

913
/**
1014
* Parser for commandline arguments.
@@ -18,7 +22,7 @@ public class GCViewerArgsParser {
1822

1923
private int argumentCount;
2024
private String chartFilePath;
21-
private String gcfile;
25+
private String gcFile;
2226
private String summaryFilePath;
2327
private DataWriterType type = DataWriterType.SUMMARY;
2428

@@ -29,9 +33,19 @@ public int getArgumentCount() {
2933
public String getChartFilePath() {
3034
return chartFilePath;
3135
}
32-
33-
public String getGcfile() {
34-
return gcfile;
36+
37+
public GCResource getGcResource() {
38+
List<String> files = Arrays.asList(gcFile.split(";"));
39+
List<GCResource> resources = files.stream().map(GcResourceFile::new).collect(Collectors.toList());
40+
if (resources.isEmpty())
41+
throw new IllegalStateException("Found no valid resource!");
42+
43+
if (resources.size() == 1) {
44+
return resources.get(0);
45+
}
46+
else {
47+
return new GcResourceSeries(resources);
48+
}
3549
}
3650

3751
public String getSummaryFilePath() {
@@ -65,7 +79,7 @@ else if (typeIdx != -1) {
6579
}
6680

6781
argumentCount = argsList.size();
68-
gcfile = safeGetArgument(argsList, ARG_POS_GCFILE);
82+
gcFile = safeGetArgument(argsList, ARG_POS_GCFILE);
6983
summaryFilePath = safeGetArgument(argsList, ARG_POS_SUMMARY_FILE);
7084
chartFilePath = safeGetArgument(argsList, ARG_POS_CHART_FILE);
7185
}

src/main/java/com/tagtraum/perf/gcviewer/ctrl/GCModelLoaderController.java

+7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public interface GCModelLoaderController {
3030

3131
void open(List<GCResource> gcResourceList);
3232

33+
/**
34+
* Opens the given {@link GCResource}s as a series of rotated logfiles.
35+
*
36+
* @param gcResourceList a list of rotated gc logfiles. Ordering is not required.
37+
*/
38+
void openAsSeries(List<GCResource> gcResourceList);
39+
3340
/**
3441
* Reload all models of <code>gcDocument</code> and provide tracker. The tracker will
3542
* fire a propertyChangeEvent, as soon as all GCModelLoaders have finished loading.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.tagtraum.perf.gcviewer.ctrl.action;
2+
3+
import com.tagtraum.perf.gcviewer.ctrl.GCModelLoaderController;
4+
import com.tagtraum.perf.gcviewer.model.GCResource;
5+
import com.tagtraum.perf.gcviewer.model.GcResourceFile;
6+
import com.tagtraum.perf.gcviewer.util.LocalisationHelper;
7+
import com.tagtraum.perf.gcviewer.view.ActionCommands;
8+
import com.tagtraum.perf.gcviewer.view.GCViewerGui;
9+
import com.tagtraum.perf.gcviewer.view.OpenFileView;
10+
import com.tagtraum.perf.gcviewer.view.util.ImageHelper;
11+
12+
import javax.swing.*;
13+
import java.awt.*;
14+
import java.awt.event.ActionEvent;
15+
import java.io.File;
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.logging.Logger;
19+
20+
/**
21+
* Allows to open a series of log files, treating them as a consecutive log.
22+
*
23+
* @author martin.geldmacher
24+
*/
25+
public class OpenSeries extends AbstractAction {
26+
private static final Logger logger = Logger.getLogger(OpenSeries.class.getName());
27+
28+
private GCModelLoaderController controller;
29+
private GCViewerGui gcViewer;
30+
private OpenFileView openFileView;
31+
32+
public OpenSeries(GCModelLoaderController controller, final GCViewerGui gcViewer) {
33+
this.controller = controller;
34+
this.gcViewer = gcViewer;
35+
36+
putValue(NAME, LocalisationHelper.getString("main_frame_menuitem_open_series"));
37+
putValue(SHORT_DESCRIPTION, LocalisationHelper.getString("main_frame_menuitem_hint_open_series"));
38+
putValue(MNEMONIC_KEY, Integer.valueOf(LocalisationHelper.getString("main_frame_menuitem_mnemonic_open_series").charAt(0)));
39+
putValue(ACTION_COMMAND_KEY, ActionCommands.OPEN_SERIES.toString());
40+
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
41+
putValue(SMALL_ICON, ImageHelper.loadImageIcon("open.png"));
42+
43+
openFileView = new OpenFileView();
44+
}
45+
46+
@Override
47+
public void actionPerformed(ActionEvent e) {
48+
final int val = openFileView.showOpenDialog(gcViewer);
49+
if (val == JFileChooser.APPROVE_OPTION) {
50+
File[] selectedFiles = openFileView.getSelectedFiles();
51+
List<GCResource> resources = getResources(selectedFiles);
52+
controller.openAsSeries(resources);
53+
}
54+
}
55+
56+
private List<GCResource> getResources(File[] selectedFiles) {
57+
if (selectedFiles == null || selectedFiles.length == 0)
58+
throw new IllegalArgumentException("At least one file must be selected!");
59+
60+
java.util.List<GCResource> resources = new ArrayList<>();
61+
for (File file : selectedFiles) {
62+
resources.add(new GcResourceFile(file));
63+
}
64+
return resources;
65+
}
66+
}

src/main/java/com/tagtraum/perf/gcviewer/ctrl/action/OpenURL.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package com.tagtraum.perf.gcviewer.ctrl.action;
22

3-
import java.awt.Toolkit;
4-
import java.awt.event.ActionEvent;
5-
6-
import javax.swing.AbstractAction;
7-
import javax.swing.JFrame;
8-
import javax.swing.KeyStroke;
9-
103
import com.tagtraum.perf.gcviewer.ctrl.GCModelLoaderController;
11-
import com.tagtraum.perf.gcviewer.model.GCResource;
4+
import com.tagtraum.perf.gcviewer.model.GcResourceFile;
125
import com.tagtraum.perf.gcviewer.util.LocalisationHelper;
136
import com.tagtraum.perf.gcviewer.view.ActionCommands;
147
import com.tagtraum.perf.gcviewer.view.OpenUrlView;
158
import com.tagtraum.perf.gcviewer.view.model.RecentGCResourcesModel;
169
import com.tagtraum.perf.gcviewer.view.util.ImageHelper;
1710

11+
import javax.swing.*;
12+
import java.awt.*;
13+
import java.awt.event.ActionEvent;
14+
1815
/**
1916
* @author <a href="mailto:[email protected]">Hendrik Schreiber</a>
2017
* Date: May 20, 2005
@@ -43,10 +40,10 @@ public void setRecentResourceNamesModel(RecentGCResourcesModel recentResourceNam
4340
public void actionPerformed(ActionEvent e) {
4441
if (view.showDialog()) {
4542
if (view.isAddCheckBoxSelected()) {
46-
controller.add(new GCResource(view.getSelectedItem()));
43+
controller.add(new GcResourceFile(view.getSelectedItem()));
4744
}
4845
else {
49-
controller.open(new GCResource(view.getSelectedItem()));
46+
controller.open(new GcResourceFile(view.getSelectedItem()));
5047
}
5148
}
5249
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.tagtraum.perf.gcviewer.ctrl.impl;
2+
3+
import com.tagtraum.perf.gcviewer.ctrl.GCModelLoader;
4+
import com.tagtraum.perf.gcviewer.imp.DataReaderException;
5+
import com.tagtraum.perf.gcviewer.imp.MonitoredBufferedInputStream;
6+
import com.tagtraum.perf.gcviewer.model.GCModel;
7+
8+
import javax.swing.*;
9+
import java.beans.PropertyChangeEvent;
10+
import java.util.concurrent.ExecutionException;
11+
import java.util.logging.Level;
12+
import java.util.logging.Logger;
13+
14+
/**
15+
* Base class for {@link GCModelLoader}s
16+
*
17+
* @author martin.geldmacher (refactored)
18+
*/
19+
public abstract class AbstractGCModelLoaderImpl extends SwingWorker<GCModel, Object> implements GCModelLoader {
20+
@Override
21+
public void propertyChange(PropertyChangeEvent evt) {
22+
if (evt.getPropertyName() == MonitoredBufferedInputStream.PROGRESS) {
23+
setProgress((int) evt.getNewValue());
24+
}
25+
}
26+
27+
protected void done() {
28+
Logger logger = getGcResource().getLogger();
29+
30+
try {
31+
getGcResource().setModel(get());
32+
// TODO delete
33+
getGcResource().getModel().printDetailedInformation();
34+
}
35+
catch (InterruptedException e) {
36+
logger.log(Level.FINE, "model get() interrupted", e);
37+
}
38+
catch (ExecutionException | RuntimeException e) {
39+
if (logger.isLoggable(Level.WARNING))
40+
logger.log(Level.WARNING, "Failed to create GCModel from " + getGcResource().getResourceName(), e);
41+
}
42+
}
43+
44+
@Override
45+
protected GCModel doInBackground() throws Exception {
46+
setProgress(0);
47+
final GCModel result;
48+
try {
49+
result = loadGcModel();
50+
}
51+
catch (DataReaderException | RuntimeException e) {
52+
Logger logger = getGcResource().getLogger();
53+
if (logger.isLoggable(Level.FINE)) {
54+
logger.log(Level.FINE, "Failed to load GCModel from " + getGcResource().getResourceName(), e);
55+
}
56+
throw e;
57+
}
58+
return result;
59+
}
60+
61+
protected abstract GCModel loadGcModel() throws DataReaderException;
62+
}

0 commit comments

Comments
 (0)