/*
* Copyright 2008-2017 by Emeric Vernat
*
* This file is part of Java Melody.
*
* 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 net.bull.javamelody;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.text.DecimalFormat;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import net.bull.javamelody.swing.MButton;
/**
* Panel du détail d'une requête.
* @author Emeric Vernat
*/
class CounterRequestDetailPanel extends MelodyPanel {
private static final long serialVersionUID = 1L;
private final CounterRequest request;
CounterRequestDetailPanel(RemoteCollector remoteCollector, CounterRequest request)
throws IOException {
super(remoteCollector);
assert request != null;
this.request = request;
refresh();
}
final void refresh() throws IOException {
removeAll();
final String graphName = request.getId();
final String graphLabel = truncate(request.getName(), 50);
setName(graphLabel);
final JPanel panel = new JPanel(new BorderLayout());
final JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.getVerticalScrollBar().setFocusable(false);
scrollPane.getHorizontalScrollBar().setFocusable(false);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
final JPanel northPanel = new JPanel(new BorderLayout());
if (request.getRumData() != null && request.getRumData().getHits() != 0) {
final JPanel requestRumDataPanel = createRequestRumDataPanel();
requestRumDataPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0));
northPanel.add(requestRumDataPanel, BorderLayout.WEST);
}
final RemoteCollector remoteCollector = getRemoteCollector();
final CounterRequestDetailTablePanel counterRequestDetailTablePanel = new CounterRequestDetailTablePanel(
remoteCollector, request);
counterRequestDetailTablePanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
northPanel.add(counterRequestDetailTablePanel, BorderLayout.SOUTH);
panel.add(northPanel, BorderLayout.NORTH);
if (CounterRequestTable.isRequestGraphDisplayed(getCounterByRequestId(request))) {
final MButton refreshButton = createRefreshButton();
refreshButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
getRemoteCollector().collectDataIncludingCurrentRequests();
refresh();
} catch (final IOException ex) {
showException(ex);
}
}
});
final ChartPanel chartPanel = new ChartPanel(remoteCollector, graphName, graphLabel,
refreshButton);
panel.add(chartPanel, BorderLayout.CENTER);
}
if (JdbcWrapper.SINGLETON.getSqlCounter().isRequestIdFromThisCounter(graphName)
&& !request.getName().toLowerCase().startsWith("alter ")) {
// inutile d'essayer d'avoir le plan d'exécution des requêtes sql
// telles que "alter session set ..." (cf issue 152)
final String sqlRequestExplainPlan = remoteCollector
.collectSqlRequestExplainPlan(request.getName());
if (sqlRequestExplainPlan != null) {
final JPanel planPanel = createSqlRequestExplainPlanPanel(sqlRequestExplainPlan);
panel.add(planPanel, BorderLayout.SOUTH);
}
} else if (request.getStackTrace() != null) {
// il n'est pas actuellement possible qu'il y ait à la fois un plan d'exécution et une stack-trace
final JPanel stackTracePanel = createStackTracePanel(request.getStackTrace());
panel.add(stackTracePanel, BorderLayout.SOUTH);
}
add(scrollPane);
}
private JPanel createRequestRumDataPanel() {
final JPanel rumDataPanel = new JPanel(new GridLayout(1, 4, 40, 0));
final CounterRequestRumData rumData = request.getRumData();
final DecimalFormat percentFormat = I18N.createPercentFormat();
final DecimalFormat integerFormat = I18N.createIntegerFormat();
final int networkTimeMean = rumData.getNetworkTimeMean();
final int serverMean = request.getMean();
final int domProcessingMean = rumData.getDomProcessingMean();
final int pageRenderingMean = rumData.getPageRenderingMean();
final int total = networkTimeMean + serverMean + domProcessingMean + pageRenderingMean;
final double networkPercent = 100d * networkTimeMean / total;
final double serverPercent = 100d * serverMean / total;
final double domProcessingPercent = 100d * domProcessingMean / total;
final double pageRenderingPercent = 100d * pageRenderingMean / total;
final String networkLabel = I18N.getString("Network") + ": "
+ integerFormat.format(networkTimeMean) + " ms ("
+ percentFormat.format(networkPercent) + "%)";
final String serverLabel = I18N.getString("Server") + " : "
+ integerFormat.format(serverMean) + " ms (" + percentFormat.format(serverPercent)
+ "%)";
final String domProcessingLabel = I18N.getString("DOM_processing") + " : "
+ integerFormat.format(domProcessingMean) + " ms ("
+ percentFormat.format(domProcessingPercent) + "%)";
final String pageRenderingLabel = I18N.getString("Page_rendering") + " : "
+ integerFormat.format(pageRenderingMean) + " ms ("
+ percentFormat.format(pageRenderingPercent) + "%)";
rumDataPanel.add(new JLabel(networkLabel));
rumDataPanel.add(new JLabel(serverLabel));
rumDataPanel.add(new JLabel(domProcessingLabel));
rumDataPanel.add(new JLabel(pageRenderingLabel));
return rumDataPanel;
}
private JPanel createSqlRequestExplainPlanPanel(String sqlRequestExplainPlan) {
final JTextArea textArea = new JTextArea();
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, textArea.getFont().getSize() - 1));
textArea.setEditable(false);
textArea.setCaretPosition(0);
// background nécessaire avec la plupart des look and feels dont Nimbus,
// sinon il reste blanc malgré editable false
textArea.setBackground(Color.decode("#E6E6E6"));
textArea.setText(sqlRequestExplainPlan);
final JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
final JLabel label = new JLabel(getString("Plan_d_execution"));
label.setFont(label.getFont().deriveFont(Font.BOLD));
panel.add(label, BorderLayout.NORTH);
final JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private JPanel createStackTracePanel(String stackTrace) {
final JTextArea textArea = new JTextArea();
textArea.setFont(textArea.getFont().deriveFont((float) textArea.getFont().getSize() - 1));
textArea.setEditable(false);
textArea.setCaretPosition(0);
// background nécessaire avec la plupart des look and feels dont Nimbus,
// sinon il reste blanc malgré editable false
textArea.setBackground(Color.decode("#E6E6E6"));
textArea.setText(stackTrace);
final JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
final JLabel label = new JLabel("Stack-trace");
label.setFont(label.getFont().deriveFont(Font.BOLD));
panel.add(label, BorderLayout.NORTH);
final JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private Counter getCounterByRequestId(CounterRequest counterRequest) {
return getCollector().getCounterByRequestId(counterRequest);
}
private static String truncate(String string, int maxLength) {
return string.substring(0, Math.min(string.length(), maxLength));
}
}