Mercurial > hg > heapstats
changeset 188:44059a9aa639
Bug 3194: Time-Awareness XAxis in FXAnalyzer
Reviewed-by: ykubota
https://github.com/HeapStats/heapstats/pull/40
line wrap: on
line diff
--- a/ChangeLog Wed Nov 09 21:15:19 2016 +0900 +++ b/ChangeLog Wed Nov 09 22:31:27 2016 +0900 @@ -1,6 +1,7 @@ 2016-11-09 Yasumasa Suenaga <yasuenag@gmail.com> * Bug 3225: JVM may hang when deadlock detector and safepoint are conflicted + * Bug 3194: Time-Awareness XAxis in FXAnalyzer 2016-11-08 Yasumasa Suenaga <yasuenag@gmail.com>
--- a/analyzer/fx/heapstats.properties Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/heapstats.properties Wed Nov 09 22:31:27 2016 +0900 @@ -14,3 +14,4 @@ #plugins= reftree_fontsize=11 tickmarker=false +x_tickunit=20
--- a/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/log/tabs/LogResourcesController.java Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/log/tabs/LogResourcesController.java Wed Nov 09 22:31:27 2016 +0900 @@ -19,6 +19,7 @@ import java.net.URL; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.List; import java.util.Optional; import java.util.ResourceBundle; @@ -35,8 +36,8 @@ import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.chart.Axis; -import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; +import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.XYChart; import javafx.scene.control.Label; @@ -53,6 +54,7 @@ import jp.co.ntt.oss.heapstats.container.log.DiffData; import jp.co.ntt.oss.heapstats.container.log.LogData; import jp.co.ntt.oss.heapstats.container.log.SummaryData; +import jp.co.ntt.oss.heapstats.utils.EpochTimeConverter; import jp.co.ntt.oss.heapstats.utils.HeapStatsUtils; /** @@ -64,59 +66,59 @@ private GridPane chartGrid; @FXML - private StackedAreaChart<String, Double> javaCPUChart; + private StackedAreaChart<Number, Double> javaCPUChart; - private XYChart.Series<String, Double> javaUserUsage; + private XYChart.Series<Number, Double> javaUserUsage; - private XYChart.Series<String, Double> javaSysUsage; + private XYChart.Series<Number, Double> javaSysUsage; @FXML - private StackedAreaChart<String, Double> systemCPUChart; + private StackedAreaChart<Number, Double> systemCPUChart; - private XYChart.Series<String, Double> systemUserUsage; + private XYChart.Series<Number, Double> systemUserUsage; - private XYChart.Series<String, Double> systemNiceUsage; + private XYChart.Series<Number, Double> systemNiceUsage; - private XYChart.Series<String, Double> systemSysUsage; + private XYChart.Series<Number, Double> systemSysUsage; - private XYChart.Series<String, Double> systemIdleUsage; + private XYChart.Series<Number, Double> systemIdleUsage; - private XYChart.Series<String, Double> systemIOWaitUsage; + private XYChart.Series<Number, Double> systemIOWaitUsage; - private XYChart.Series<String, Double> systemIRQUsage; + private XYChart.Series<Number, Double> systemIRQUsage; - private XYChart.Series<String, Double> systemSoftIRQUsage; + private XYChart.Series<Number, Double> systemSoftIRQUsage; - private XYChart.Series<String, Double> systemStealUsage; + private XYChart.Series<Number, Double> systemStealUsage; - private XYChart.Series<String, Double> systemGuestUsage; + private XYChart.Series<Number, Double> systemGuestUsage; @FXML - private LineChart<String, Long> javaMemoryChart; + private LineChart<Number, Long> javaMemoryChart; - private XYChart.Series<String, Long> javaVSZUsage; + private XYChart.Series<Number, Long> javaVSZUsage; - private XYChart.Series<String, Long> javaRSSUsage; + private XYChart.Series<Number, Long> javaRSSUsage; @FXML - private LineChart<String, Long> safepointChart; + private LineChart<Number, Long> safepointChart; - private XYChart.Series<String, Long> safepoints; + private XYChart.Series<Number, Long> safepoints; @FXML - private LineChart<String, Long> safepointTimeChart; + private LineChart<Number, Long> safepointTimeChart; - private XYChart.Series<String, Long> safepointTime; + private XYChart.Series<Number, Long> safepointTime; @FXML - private LineChart<String, Long> threadChart; + private LineChart<Number, Long> threadChart; - private XYChart.Series<String, Long> threads; + private XYChart.Series<Number, Long> threads; @FXML - private LineChart<String, Long> monitorChart; + private LineChart<Number, Long> monitorChart; - private XYChart.Series<String, Long> monitors; + private XYChart.Series<Number, Long> monitors; @FXML private TableView<SummaryData.SummaryDataEntry> procSummary; @@ -136,6 +138,8 @@ private List<LocalDateTime> suspectList; private ResourceBundle resource; + + private EpochTimeConverter epochTimeConverter; /** * Initializes the controller class. @@ -159,6 +163,8 @@ popupText.setStyle("-fx-font-family: monospace; -fx-text-fill: white; -fx-background-color: black;"); chartPopup.getContent().add(popupText); archiveList = new SimpleObjectProperty<>(); + + epochTimeConverter = new EpochTimeConverter(); } /** @@ -227,25 +233,31 @@ * @param event Mouse event. * @param labelFunc Function to format label string. */ - private void showChartPopup(XYChart<String, ? extends Number> chart, String xValue, MouseEvent event, Function<? super Number, String> labelFunc) { - String label = chart.getData().stream() - .map(s -> s.getName() + " = " + s.getData().stream() - .filter(d -> d.getXValue().equals(xValue)) - .map(d -> labelFunc.apply(d.getYValue())) - .findAny() - .orElse("<none>")) - .collect(Collectors.joining("\n")); - - popupText.setText(xValue + "\n" + label); - chartPopup.show(chart, event.getScreenX() + 15.0d, event.getScreenY() + 3.0d); + private void showChartPopup(XYChart<Number, ? extends Number> chart, Number xValue, MouseEvent event, Function<? super Number, String> labelFunc) { + boolean isContained = chart.getData() + .stream() + .flatMap(s -> s.getData().stream()) + .anyMatch(d -> d.getXValue().longValue() == xValue.longValue()); + if(isContained){ + String label = chart.getData() + .stream() + .map(s -> s.getName() + " = " + s.getData() + .stream() + .filter(d -> d.getXValue().longValue() == xValue.longValue()) + .map(d -> labelFunc.apply(d.getYValue())) + .findAny() + .get()) + .collect(Collectors.joining("\n")); + popupText.setText(epochTimeConverter.toString(xValue) + "\n" + label); + chartPopup.show(chart, event.getScreenX() + 15.0d, event.getScreenY() + 3.0d); + } } @FXML @SuppressWarnings("unchecked") private void onChartMouseMoved(MouseEvent event) { - XYChart<String, ? extends Number> chart = (XYChart<String, ? extends Number>) event.getSource(); - CategoryAxis xAxis = (CategoryAxis) chart.getXAxis(); - double startXPoint = xAxis.getLayoutX() + xAxis.getStartMargin(); + XYChart<Number, ? extends Number> chart = (XYChart<Number, ? extends Number>) event.getSource(); + NumberAxis xAxis = (NumberAxis)chart.getXAxis(); Function<? super Number, String> labelFunc; if ((chart == javaCPUChart) || (chart == systemCPUChart)) { @@ -258,7 +270,7 @@ labelFunc = d -> d.toString(); } - Optional.ofNullable(chart.getXAxis().getValueForDisplay(event.getX() - startXPoint)) + Optional.ofNullable(chart.getXAxis().getValueForDisplay(event.getX() - xAxis.getLayoutX())) .ifPresent(v -> showChartPopup(chart, v, event, labelFunc)); } @@ -267,7 +279,7 @@ chartPopup.hide(); } - private void drawLineInternal(StackPane target, List<String> drawList, String style) { + private void drawLineInternal(StackPane target, List<Number> drawList, String style) { AnchorPane anchor = null; XYChart chart = null; @@ -296,17 +308,17 @@ .filter(r -> r.getStyle().equals(style)) .collect(Collectors.toList())); - CategoryAxis xAxis = (CategoryAxis) chart.getXAxis(); + NumberAxis xAxis = (NumberAxis) chart.getXAxis(); Axis yAxis = chart.getYAxis(); Label chartTitle = (Label) chart.getChildrenUnmodifiable().stream() .filter(n -> n.getStyleClass().contains("chart-title")) .findFirst() .get(); - double startX = xAxis.getLayoutX() + xAxis.getStartMargin() - 1.0d; + double startX = xAxis.getLayoutX() + 4.0d; double yPos = yAxis.getLayoutY() + chartTitle.getLayoutY() + chartTitle.getHeight(); List<Rectangle> rectList = drawList.stream() - .map(s -> new Rectangle(xAxis.getDisplayPosition(s) + startX, yPos, 2.0d, yAxis.getHeight())) + .map(t -> new Rectangle(xAxis.getDisplayPosition(t) + startX, yPos, 2.0d, yAxis.getHeight())) .peek(r -> ((Rectangle) r).setStyle(style)) .collect(Collectors.toList()); anchorChildren.addAll(rectList); @@ -318,9 +330,10 @@ return; } - List<String> archiveDateList = archiveList.get().stream() - .map(a -> a.getDate().format(HeapStatsUtils.getDateTimeFormatter())) - .collect(Collectors.toList()); + List<Number> archiveDateList = archiveList.get() + .stream() + .map(a -> a.getDate().atZone(ZoneId.systemDefault()).toEpochSecond()) + .collect(Collectors.toList()); chartGrid.getChildren().stream() .filter(n -> n instanceof StackPane) .forEach(p -> drawLineInternal((StackPane) p, archiveDateList, "-fx-fill: black;")); @@ -337,9 +350,9 @@ return; } - List<String> suspectRebootDateList = suspectList.stream() - .map(d -> d.format(HeapStatsUtils.getDateTimeFormatter())) - .collect(Collectors.toList()); + List<Number> suspectRebootDateList = suspectList.stream() + .map(d -> d.atZone(ZoneId.systemDefault()).toEpochSecond()) + .collect(Collectors.toList()); chartGrid.getChildren().stream() .filter(n -> n instanceof StackPane) .forEach(p -> drawLineInternal((StackPane) p, suspectRebootDateList, "-fx-fill: yellow;")); @@ -359,33 +372,33 @@ private class DrawLogChartTask extends Task<Void> { /* Java CPU */ - private final ObservableList<XYChart.Data<String, Double>> javaUserUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> javaSysUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> javaUserUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> javaSysUsageBuf; /* System CPU */ - private final ObservableList<XYChart.Data<String, Double>> systemUserUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemNiceUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemSysUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemIdleUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemIOWaitUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemIRQUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemSoftIRQUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemStealUsageBuf; - private final ObservableList<XYChart.Data<String, Double>> systemGuestUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemUserUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemNiceUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemSysUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemIdleUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemIOWaitUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemIRQUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemSoftIRQUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemStealUsageBuf; + private final ObservableList<XYChart.Data<Number, Double>> systemGuestUsageBuf; /* Java Memory */ - private final ObservableList<XYChart.Data<String, Long>> javaVSZUsageBuf; - private final ObservableList<XYChart.Data<String, Long>> javaRSSUsageBuf; + private final ObservableList<XYChart.Data<Number, Long>> javaVSZUsageBuf; + private final ObservableList<XYChart.Data<Number, Long>> javaRSSUsageBuf; /* Safepoints */ - private final ObservableList<XYChart.Data<String, Long>> safepointsBuf; - private final ObservableList<XYChart.Data<String, Long>> safepointTimeBuf; + private final ObservableList<XYChart.Data<Number, Long>> safepointsBuf; + private final ObservableList<XYChart.Data<Number, Long>> safepointTimeBuf; /* Threads */ - private final ObservableList<XYChart.Data<String, Long>> threadsBuf; + private final ObservableList<XYChart.Data<Number, Long>> threadsBuf; /* Monitor contantion */ - private final ObservableList<XYChart.Data<String, Long>> monitorsBuf; + private final ObservableList<XYChart.Data<Number, Long>> monitorsBuf; private final List<LogData> targetLogData; @@ -420,7 +433,7 @@ } private void addDiffData(DiffData data) { - String time = data.getDateTime().format(HeapStatsUtils.getDateTimeFormatter()); + long time = data.getDateTime().atZone(ZoneId.systemDefault()).toEpochSecond(); javaUserUsageBuf.add(new XYChart.Data<>(time, data.getJavaUserUsage())); javaSysUsageBuf.add(new XYChart.Data<>(time, data.getJavaSysUsage())); @@ -441,7 +454,7 @@ } private void addLogData(LogData data) { - String time = data.getDateTime().format(HeapStatsUtils.getDateTimeFormatter()); + long time = data.getDateTime().atZone(ZoneId.systemDefault()).toEpochSecond(); javaVSZUsageBuf.add(new XYChart.Data<>(time, data.getJavaVSSize() / 1024 / 1024)); javaRSSUsageBuf.add(new XYChart.Data<>(time, data.getJavaRSSize() / 1024 / 1024)); @@ -451,6 +464,22 @@ } private void setChartData() { + /* Set chart range */ + long startLogEpoch = targetLogData.get(0).getDateTime().atZone(ZoneId.systemDefault()).toEpochSecond(); + long endLogEpoch = targetLogData.get(targetLogData.size() - 1).getDateTime().atZone(ZoneId.systemDefault()).toEpochSecond(); + long startDiffEpoch = targetDiffData.get(0).getDateTime().atZone(ZoneId.systemDefault()).toEpochSecond(); + long endDiffEpoch = targetDiffData.get(targetDiffData.size() - 1).getDateTime().atZone(ZoneId.systemDefault()).toEpochSecond(); + Stream.of(javaMemoryChart, threadChart) + .map(c -> (NumberAxis)c.getXAxis()) + .peek(a -> a.setTickUnit((endLogEpoch - startLogEpoch) / HeapStatsUtils.getXTickUnit())) + .peek(a -> a.setLowerBound(startLogEpoch)) + .forEach(a -> a.setUpperBound(endLogEpoch)); + Stream.of(javaCPUChart, systemCPUChart, safepointChart, safepointTimeChart, monitorChart) + .map(c -> (NumberAxis)c.getXAxis()) + .peek(a -> a.setTickUnit((endDiffEpoch - startDiffEpoch) / HeapStatsUtils.getXTickUnit())) + .peek(a -> a.setLowerBound(startDiffEpoch)) + .forEach(a -> a.setUpperBound(endDiffEpoch)); + /* Replace new chart data */ javaUserUsage.setData(javaUserUsageBuf); javaSysUsage.setData(javaSysUsageBuf);
--- a/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/SnapShotController.java Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/SnapShotController.java Wed Nov 09 22:31:27 2016 +0900 @@ -20,6 +20,7 @@ import java.io.File; import java.net.URL; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -48,7 +49,7 @@ import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.chart.Axis; -import javafx.scene.chart.CategoryAxis; +import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; @@ -375,7 +376,7 @@ parseThread.start(); } - private void drawRebootSuspectLine(XYChart<String, ? extends Number> target) { + private void drawRebootSuspectLine(XYChart<Number, ? extends Number> target) { if (target.getData().isEmpty() || target.getData().get(0).getData().isEmpty()) { return; @@ -389,18 +390,18 @@ ObservableList<Node> anchorChildren = anchor.getChildren(); anchorChildren.clear(); - CategoryAxis xAxis = (CategoryAxis) target.getXAxis(); + NumberAxis xAxis = (NumberAxis)target.getXAxis(); Axis yAxis = target.getYAxis(); Label chartTitle = (Label) target.getChildrenUnmodifiable().stream() .filter(n -> n.getStyleClass().contains("chart-title")) .findFirst() .get(); - double startX = xAxis.getLayoutX() + xAxis.getStartMargin() - 1.0d; + double startX = xAxis.getLayoutX() + 4.0d; double yPos = yAxis.getLayoutY() + chartTitle.getLayoutY() + chartTitle.getHeight(); List<Rectangle> rectList = summaryData.get().getRebootSuspectList() .stream() - .map(d -> d.format(HeapStatsUtils.getDateTimeFormatter())) + .map(d -> d.atZone(ZoneId.systemDefault()).toEpochSecond()) .map(s -> new Rectangle(xAxis.getDisplayPosition(s) + startX, yPos, 4d, yAxis.getHeight())) .peek(r -> ((Rectangle) r).setStyle("-fx-fill: yellow;")) .collect(Collectors.toList());
--- a/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/HistogramController.java Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/HistogramController.java Wed Nov 09 22:31:27 2016 +0900 @@ -20,6 +20,7 @@ import java.io.File; import java.net.URL; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -103,7 +104,7 @@ private Button selectFilterApplyBtn; @FXML - private StackedAreaChart<String, Long> topNChart; + private StackedAreaChart<Number, Long> topNChart; @FXML private AnchorPane topNChartAnchor; @@ -145,7 +146,7 @@ private LongProperty currentObjectTag; - private Consumer<XYChart<String, ? extends Number>> drawRebootSuspectLine; + private Consumer<XYChart<Number, ? extends Number>> drawRebootSuspectLine; private Consumer<Task<Void>> taskExecutor; @@ -224,8 +225,8 @@ * chart series as value. * @param objData ObjectData which is you want to build. */ - private void buildTopNChartData(SnapShotHeader header, Map<String, XYChart.Series<String, Long>> seriesMap, ObjectData objData) { - XYChart.Series<String, Long> series = seriesMap.get(objData.getName()); + private void buildTopNChartData(SnapShotHeader header, Map<String, XYChart.Series<Number, Long>> seriesMap, ObjectData objData) { + XYChart.Series<Number, Long> series = seriesMap.get(objData.getName()); if (series == null) { series = new XYChart.Series<>(); @@ -234,10 +235,10 @@ seriesMap.put(objData.getName(), series); } - String time = header.getSnapShotDate().format(HeapStatsUtils.getDateTimeFormatter()); + long time = header.getSnapShotDate().atZone(ZoneId.systemDefault()).toEpochSecond(); long yValue = instanceGraph.get() ? objData.getCount() : objData.getTotalSize() / 1024 / 1024; - XYChart.Data<String, Long> data = new XYChart.Data<>(time, yValue); + XYChart.Data<Number, Long> data = new XYChart.Data<>(time, yValue); series.getData().add(data); String unit = instanceGraph.get() ? "instances" : "MB"; @@ -245,7 +246,7 @@ Tooltip.install(data.getNode(), new Tooltip(tip)); } - private void setTopNChartColor(XYChart.Series<String, Long> series) { + private void setTopNChartColor(XYChart.Series<Number, Long> series) { String color = ChartColorManager.getNextColor(series.getName()); series.getNode().lookup(".chart-series-area-line").setStyle(String.format("-fx-stroke: %s;", color)); @@ -263,7 +264,15 @@ * @param seriesMap Chart series map which is contains class name as key, * chart series as value. */ - private void onDiffTaskSucceeded(DiffCalculator diff, Map<String, XYChart.Series<String, Long>> seriesMap) { + private void onDiffTaskSucceeded(DiffCalculator diff, Map<String, XYChart.Series<Number, Long>> seriesMap) { + /* Set chart range */ + long startEpoch = currentTarget.get().get(0).getSnapShotDate().atZone(ZoneId.systemDefault()).toEpochSecond(); + long endEpoch = currentTarget.get().get(currentTarget.get().size() - 1).getSnapShotDate().atZone(ZoneId.systemDefault()).toEpochSecond(); + NumberAxis xAxis = (NumberAxis)topNChart.getXAxis(); + xAxis.setTickUnit((endEpoch - startEpoch) / HeapStatsUtils.getXTickUnit()); + xAxis.setLowerBound(startEpoch); + xAxis.setUpperBound(endEpoch); + topNList.set(FXCollections.observableMap(diff.getTopNList())); currentTarget.get().stream() @@ -443,7 +452,7 @@ public Task<Void> getDrawTopNDataTask(List<SnapShotHeader> target, boolean includeOthers, Predicate<? super ObjectData> predicate) { topNChart.getData().clear(); lastDiffTable.getItems().clear(); - Map<String, XYChart.Series<String, Long>> seriesMap = new HashMap<>(); + Map<String, XYChart.Series<Number, Long>> seriesMap = new HashMap<>(); TaskAdapter<DiffCalculator> diff = new TaskAdapter<>(new DiffCalculator(target, HeapStatsUtils.getRankLevel(), includeOthers, predicate, HeapStatsUtils.getReplaceClassName(), instanceGraph.get())); @@ -457,7 +466,7 @@ * * @param drawRebootSuspectLine Consumer for drawing reboot line. */ - public void setDrawRebootSuspectLine(Consumer<XYChart<String, ? extends Number>> drawRebootSuspectLine) { + public void setDrawRebootSuspectLine(Consumer<XYChart<Number, ? extends Number>> drawRebootSuspectLine) { this.drawRebootSuspectLine = drawRebootSuspectLine; } @@ -513,7 +522,7 @@ * * @return TopN chart. */ - public StackedAreaChart<String, Long> getTopNChart() { + public StackedAreaChart<Number, Long> getTopNChart() { return topNChart; }
--- a/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/SummaryController.java Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/SummaryController.java Wed Nov 09 22:31:27 2016 +0900 @@ -18,6 +18,7 @@ package jp.co.ntt.oss.heapstats.plugin.builtin.snapshot.tabs; import java.net.URL; +import java.time.ZoneId; import java.util.Locale; import java.util.ResourceBundle; import java.util.function.Consumer; @@ -34,14 +35,17 @@ import javafx.fxml.Initializable; import javafx.scene.chart.AreaChart; import javafx.scene.chart.LineChart; +import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.XYChart; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.AnchorPane; +import javafx.util.StringConverter; import jp.co.ntt.oss.heapstats.container.snapshot.SnapShotHeader; import jp.co.ntt.oss.heapstats.container.snapshot.SummaryData; +import jp.co.ntt.oss.heapstats.utils.EpochTimeConverter; import jp.co.ntt.oss.heapstats.utils.HeapStatsUtils; /** @@ -59,30 +63,30 @@ private TableColumn<SummaryData.SummaryDataEntry, String> valueColumn; @FXML - private StackedAreaChart<String, Long> heapChart; + private StackedAreaChart<Number, Long> heapChart; - private XYChart.Series<String, Long> youngUsage; + private XYChart.Series<Number, Long> youngUsage; - private XYChart.Series<String, Long> oldUsage; + private XYChart.Series<Number, Long> oldUsage; - private XYChart.Series<String, Long> free; + private XYChart.Series<Number, Long> free; @FXML - private LineChart<String, Long> instanceChart; + private LineChart<Number, Long> instanceChart; - private XYChart.Series<String, Long> instances; + private XYChart.Series<Number, Long> instances; @FXML - private LineChart<String, Long> gcTimeChart; + private LineChart<Number, Long> gcTimeChart; - private XYChart.Series<String, Long> gcTime; + private XYChart.Series<Number, Long> gcTime; @FXML - private AreaChart<String, Long> metaspaceChart; + private AreaChart<Number, Long> metaspaceChart; - private XYChart.Series<String, Long> metaspaceUsage; + private XYChart.Series<Number, Long> metaspaceUsage; - private XYChart.Series<String, Long> metaspaceCapacity; + private XYChart.Series<Number, Long> metaspaceCapacity; private ObjectProperty<SummaryData> summaryData; @@ -108,6 +112,11 @@ .peek(c -> c.lookup(".chart").setStyle(bgcolor)) .forEach(c -> c.getXAxis().setTickMarkVisible(HeapStatsUtils.getTickMarkerSwitch())); + StringConverter<Number> converter = new EpochTimeConverter(); + Stream.of(heapChart, instanceChart, gcTimeChart, metaspaceChart) + .map(c -> (NumberAxis)c.getXAxis()) + .forEach(a -> a.setTickLabelFormatter(converter)); + initializeChartSeries(); } @@ -181,22 +190,22 @@ private int processedIndex; - private final Consumer<XYChart<String, ? extends Number>> drawRebootSuspectLine; + private final Consumer<XYChart<Number, ? extends Number>> drawRebootSuspectLine; /* Java Heap Usage Chart */ - private final ObservableList<XYChart.Data<String, Long>> youngUsageBuf; - private final ObservableList<XYChart.Data<String, Long>> oldUsageBuf; - private final ObservableList<XYChart.Data<String, Long>> freeBuf; + private final ObservableList<XYChart.Data<Number, Long>> youngUsageBuf; + private final ObservableList<XYChart.Data<Number, Long>> oldUsageBuf; + private final ObservableList<XYChart.Data<Number, Long>> freeBuf; /* Instances */ - private final ObservableList<XYChart.Data<String, Long>> instanceBuf; + private final ObservableList<XYChart.Data<Number, Long>> instanceBuf; /* GC time Chart */ - private final ObservableList<XYChart.Data<String, Long>> gcTimeBuf; + private final ObservableList<XYChart.Data<Number, Long>> gcTimeBuf; /* Metaspace Chart */ - private final ObservableList<XYChart.Data<String, Long>> metaspaceUsageBuf; - private final ObservableList<XYChart.Data<String, Long>> metaspaceCapacityBuf; + private final ObservableList<XYChart.Data<Number, Long>> metaspaceUsageBuf; + private final ObservableList<XYChart.Data<Number, Long>> metaspaceCapacityBuf; /** * Constructor of CalculateGCSummaryTask. @@ -204,7 +213,7 @@ * @param drawRebootSuspectLine Consumer for drawing reboot line. This * consumer is called in Platform#runLater() at succeeded(). */ - public CalculateGCSummaryTask(Consumer<XYChart<String, ? extends Number>> drawRebootSuspectLine) { + public CalculateGCSummaryTask(Consumer<XYChart<Number, ? extends Number>> drawRebootSuspectLine) { this.drawRebootSuspectLine = drawRebootSuspectLine; youngUsageBuf = FXCollections.observableArrayList(); @@ -217,7 +226,7 @@ } private void processSnapShotHeader(SnapShotHeader header) { - String time = header.getSnapShotDate().format(HeapStatsUtils.getDateTimeFormatter()); + long time = header.getSnapShotDate().atZone(ZoneId.systemDefault()).toEpochSecond(); youngUsageBuf.add(new XYChart.Data<>(time, header.getNewHeap() / 1024 / 1024)); oldUsageBuf.add(new XYChart.Data<>(time, header.getOldHeap() / 1024 / 1024)); @@ -250,6 +259,14 @@ @Override protected void succeeded() { + long startEpoch = currentTarget.get().get(0).getSnapShotDate().atZone(ZoneId.systemDefault()).toEpochSecond(); + long endEpoch = currentTarget.get().get(currentTarget.get().size() - 1).getSnapShotDate().atZone(ZoneId.systemDefault()).toEpochSecond(); + Stream.of(heapChart, instanceChart, gcTimeChart, metaspaceChart) + .peek(c -> ((NumberAxis)c.getXAxis()).setTickUnit((endEpoch - startEpoch) / HeapStatsUtils.getXTickUnit())) + .peek(c -> ((NumberAxis)c.getXAxis()).setLowerBound(startEpoch)) + .peek(c -> ((NumberAxis)c.getXAxis()).setUpperBound(endEpoch)) + .forEach(c -> Platform.runLater(() -> drawRebootSuspectLine.accept(c))); + /* Replace new chart data */ youngUsage.setData(youngUsageBuf); oldUsage.setData(oldUsageBuf); @@ -261,9 +278,6 @@ metaspaceUsage.setData(metaspaceUsageBuf); metaspaceCapacity.setData(metaspaceCapacityBuf); - - Stream.of(heapChart, instanceChart, gcTimeChart, metaspaceChart) - .forEach(c -> Platform.runLater(() -> drawRebootSuspectLine.accept(c))); } } @@ -301,7 +315,7 @@ * @param drawRebootSuspectLine Consumer for drawing reboot line. * @return Task for calculating GC summary. */ - public Task<Void> getCalculateGCSummaryTask(Consumer<XYChart<String, ? extends Number>> drawRebootSuspectLine) { + public Task<Void> getCalculateGCSummaryTask(Consumer<XYChart<Number, ? extends Number>> drawRebootSuspectLine) { return new CalculateGCSummaryTask(drawRebootSuspectLine); } @@ -310,7 +324,7 @@ * * @return Java heap chart. */ - public StackedAreaChart<String, Long> getHeapChart() { + public StackedAreaChart<Number, Long> getHeapChart() { return heapChart; } @@ -319,7 +333,7 @@ * * @return Instance chart. */ - public LineChart<String, Long> getInstanceChart() { + public LineChart<Number, Long> getInstanceChart() { return instanceChart; } @@ -328,7 +342,7 @@ * * @return GC time chart. */ - public LineChart<String, Long> getGcTimeChart() { + public LineChart<Number, Long> getGcTimeChart() { return gcTimeChart; } @@ -337,7 +351,7 @@ * * @return Metaspace chart. */ - public AreaChart<String, Long> getMetaspaceChart() { + public AreaChart<Number, Long> getMetaspaceChart() { return metaspaceChart; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/utils/EpochTimeConverter.java Wed Nov 09 22:31:27 2016 +0900 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Yasumasa Suenaga + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package jp.co.ntt.oss.heapstats.utils; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import javafx.util.StringConverter; + +/** + * String converter for epoch time. + * This class supports SECOND time unit ONLY. + * + * @author Yasumasa Suenaga + */ +public class EpochTimeConverter extends StringConverter<Number>{ + + @Override + public String toString(Number object) { + return LocalDateTime.ofInstant(Instant.ofEpochSecond(object.longValue()), ZoneId.systemDefault()).format(HeapStatsUtils.getDateTimeFormatter()); + } + + @Override + public Number fromString(String string) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + +}
--- a/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/utils/HeapStatsUtils.java Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/java/jp/co/ntt/oss/heapstats/utils/HeapStatsUtils.java Wed Nov 09 22:31:27 2016 +0900 @@ -194,6 +194,18 @@ prop.setProperty("tickmarker", "false"); } + /* TickUnit of X axis */ + String xTickUnitStr = prop.getProperty("x_tickunit"); + if (xTickUnitStr == null) { + prop.setProperty("x_tickunit", "20"); + } else { + try { + Double.parseDouble(xTickUnitStr); + } catch (NumberFormatException e) { + throw new HeapStatsConfigException(resource.getString("invalid.option") + " x_tickunit=" + xTickUnitStr, e); + } + } + /* Add shutdown hook for saving current settings. */ Runnable savePropImpl = () -> { try (OutputStream out = Files.newOutputStream(properties, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE)) { @@ -354,6 +366,15 @@ } /** + * Get TickUnit on X axis. + * + * @return TickUnit of X axis. + */ + public static double getXTickUnit(){ + return Double.parseDouble(prop.getProperty("x_tickunit")); + } + + /** * Convert stack trace to String. * * @param e Throwable object to convert.
--- a/analyzer/fx/src/main/resources/jp/co/ntt/oss/heapstats/plugin/builtin/log/tabs/resources.fxml Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/resources/jp/co/ntt/oss/heapstats/plugin/builtin/log/tabs/resources.fxml Wed Nov 09 22:31:27 2016 +0900 @@ -41,7 +41,7 @@ <children> <LineChart id="threadChart" fx:id="threadChart" animated="false" createSymbols="false" legendVisible="false" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.thread"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis side="LEFT" minorTickVisible="false" /> @@ -63,7 +63,7 @@ <children> <StackedAreaChart id="javaCPUChart" fx:id="javaCPUChart" animated="false" createSymbols="false" legendSide="BOTTOM" legendVisible="true" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.javacpu"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis autoRanging="false" label="\%" lowerBound="0.0" side="LEFT" upperBound="100.0d" tickUnit="10.0" minorTickVisible="false" /> @@ -76,7 +76,7 @@ <children> <StackedAreaChart id="systemCPUChart" fx:id="systemCPUChart" animated="false" createSymbols="false" legendSide="BOTTOM" legendVisible="true" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.systemcpu"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis autoRanging="false" label="\%" lowerBound="0.0" side="LEFT" upperBound="100.0d" tickUnit="10.0" minorTickVisible="false" /> @@ -89,7 +89,7 @@ <children> <LineChart id="javaMemoryChart" fx:id="javaMemoryChart" animated="false" createSymbols="false" legendSide="BOTTOM" legendVisible="true" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.nativememory"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis label="MB" side="LEFT" minorTickVisible="false" /> @@ -102,7 +102,7 @@ <children> <LineChart id="safepointChart" fx:id="safepointChart" animated="false" createSymbols="false" legendVisible="false" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.safepoint.count"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" visible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" visible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis side="LEFT" minorTickVisible="false" /> @@ -115,7 +115,7 @@ <children> <LineChart id="safepointTimeChart" fx:id="safepointTimeChart" animated="false" createSymbols="false" legendVisible="false" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.safepoint.time"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" visible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" visible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis label="ms" side="LEFT" minorTickVisible="false" /> @@ -128,7 +128,7 @@ <children> <LineChart id="monitorChart" fx:id="monitorChart" animated="false" createSymbols="false" legendVisible="false" minHeight="0.0" minWidth="0.0" onMouseExited="#onChartMouseExited" onMouseMoved="#onChartMouseMoved" title="%chart.monitorcontention"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis side="LEFT" minorTickVisible="false" />
--- a/analyzer/fx/src/main/resources/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/histogram.fxml Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/resources/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/histogram.fxml Wed Nov 09 22:31:27 2016 +0900 @@ -66,7 +66,7 @@ <children> <StackedAreaChart fx:id="topNChart" animated="false" legendVisible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis fx:id="topNYAxis" autoRanging="false" label="MB" side="LEFT" minorTickVisible="false" />
--- a/analyzer/fx/src/main/resources/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/summary.fxml Wed Nov 09 21:15:19 2016 +0900 +++ b/analyzer/fx/src/main/resources/jp/co/ntt/oss/heapstats/plugin/builtin/snapshot/tabs/summary.fxml Wed Nov 09 22:31:27 2016 +0900 @@ -46,7 +46,7 @@ <children> <StackedAreaChart id="heapChart" fx:id="heapChart" animated="false" createSymbols="false" layoutX="-129.0" layoutY="-91.0" minHeight="0.0" title="%chart.javaheap" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis label="MB" side="LEFT" minorTickVisible="false" /> @@ -59,7 +59,7 @@ <children> <LineChart id="instanceChart" fx:id="instanceChart" animated="false" createSymbols="false" layoutX="-149.0" layoutY="-120.0" legendVisible="false" minHeight="0.0" title="%chart.instances" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" visible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" visible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis label="instances" side="LEFT" minorTickVisible="false" /> @@ -72,7 +72,7 @@ <children> <LineChart id="gcTimeChart" fx:id="gcTimeChart" animated="false" createSymbols="false" layoutX="-169.0" layoutY="-120.0" legendVisible="false" minHeight="0.0" title="%chart.gctime" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis label="ms" side="LEFT" minorTickVisible="false" /> @@ -85,7 +85,7 @@ <children> <AreaChart id="metaspaceChart" fx:id="metaspaceChart" animated="false" createSymbols="false" layoutX="-174.0" layoutY="-166.0" minHeight="0.0" title="%chart.metaspace" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <xAxis> - <CategoryAxis side="BOTTOM" tickLabelsVisible="false" /> + <NumberAxis side="BOTTOM" tickLabelsVisible="false" minorTickVisible="false" autoRanging="false" /> </xAxis> <yAxis> <NumberAxis label="MB" side="LEFT" minorTickVisible="false" />