/* * Copyright 2008-2014 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.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.URI; import java.net.URL; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SpringLayout; import javax.swing.SwingConstants; import net.bull.javamelody.PdfJavaInformationsReport.Bar; import net.bull.javamelody.swing.MButton; import net.bull.javamelody.swing.MHyperLink; import net.bull.javamelody.swing.util.SpringUtilities; import com.lowagie.text.Font; /** * Panel des informations systèmes. * @author Emeric Vernat */ class JavaInformationsPanel extends MelodyPanel { static final ImageIcon PLUS_ICON = ImageIconCache.getImageIcon("bullets/plus.png"); static final ImageIcon MINUS_ICON = ImageIconCache.getImageIcon("bullets/minus.png"); private static final ImageIcon XML_ICON = ImageIconCache.getScaledImageIcon("xml.png", 14, 14); private static final long serialVersionUID = 1L; private final boolean noDatabase = Parameters.isNoDatabase(); private final DecimalFormat integerFormat = I18N.createIntegerFormat(); private final DecimalFormat decimalFormat = I18N.createPercentFormat(); private final JavaInformations javaInformations; private final URL monitoringUrl; private final JPanel gridPanel; private JavaInformationsPanel detailsPanel; JavaInformationsPanel(RemoteCollector remoteCollector, JavaInformations javaInformations, URL monitoringUrl) { super(remoteCollector); assert javaInformations != null; this.javaInformations = javaInformations; this.monitoringUrl = monitoringUrl; gridPanel = new JPanel(new SpringLayout()); gridPanel.setOpaque(false); add(gridPanel, BorderLayout.NORTH); } void showSummary() { addLabel(getString("Host")); final JLabel hostLabel = new JLabel(javaInformations.getHost()); hostLabel.setFont(hostLabel.getFont().deriveFont(Font.BOLD)); addJLabel(hostLabel); final MemoryInformations memoryInformations = javaInformations.getMemoryInformations(); final long usedMemory = memoryInformations.getUsedMemory(); final long maxMemory = memoryInformations.getMaxMemory(); addLabel(getString("memoire_utilisee")); // writeGraph("usedMemory", integerFormat.format(usedMemory / 1024 / 1024)); final String divide = " / "; addJLabel(toBarWithAlert(integerFormat.format(usedMemory / 1024 / 1024) + ' ' + getString("Mo") + divide + integerFormat.format(maxMemory / 1024 / 1024) + ' ' + getString("Mo"), memoryInformations.getUsedMemoryPercentage(), "-Xmx")); if (javaInformations.getSessionCount() >= 0) { addLabel(getString("nb_sessions_http")); // writeGraph("httpSessions", integerFormat.format(javaInformations.getSessionCount())); addValue(integerFormat.format(javaInformations.getSessionCount())); } addLabel(getString("nb_threads_actifs") + "\n(" + getString("Requetes_http_en_cours") + ')'); // writeGraph("activeThreads", integerFormat.format(javaInformations.getActiveThreadCount())); addValue(integerFormat.format(javaInformations.getActiveThreadCount())); if (!noDatabase) { addLabel(getString("nb_connexions_actives")); // writeGraph("activeConnections", integerFormat.format(javaInformations.getActiveConnectionCount())); addValue(integerFormat.format(javaInformations.getActiveConnectionCount())); final int usedConnectionCount = javaInformations.getUsedConnectionCount(); final int maxConnectionCount = javaInformations.getMaxConnectionCount(); addLabel(getString("nb_connexions_utilisees") + "\n(" + getString("ouvertes") + ')'); // writeGraph("usedConnections", integerFormat.format(usedConnectionCount)); if (maxConnectionCount > 0) { addJLabel(toBarWithAlert(integerFormat.format(usedConnectionCount), javaInformations.getUsedConnectionPercentage(), null)); } else { addValue(integerFormat.format(usedConnectionCount) + divide + integerFormat.format(maxConnectionCount)); } } if (javaInformations.getSystemLoadAverage() >= 0) { addLabel(getString("Charge_systeme")); // writeGraph("systemLoad", decimalFormat.format(javaInformations.getSystemLoadAverage())); addValue(decimalFormat.format(javaInformations.getSystemLoadAverage())); } makeGrid(); } void showDetails(boolean repeatHost) { if (detailsPanel != null) { detailsPanel.setVisible(!detailsPanel.isVisible()); } else { detailsPanel = new JavaInformationsPanel(getRemoteCollector(), javaInformations, monitoringUrl); detailsPanel.addDetails(repeatHost); add(detailsPanel, BorderLayout.SOUTH); // sans cela, le panel n'apparaît pas la première fois detailsPanel.setVisible(false); detailsPanel.setVisible(true); } } private void addDetails(boolean repeatHost) { if (repeatHost) { addLabel(getString("Host")); final JLabel hostLabel = new JLabel(javaInformations.getHost()); hostLabel.setFont(hostLabel.getFont().deriveFont(Font.BOLD)); addJLabel(hostLabel); } addLabel(getString("OS")); final String osIconName = HtmlJavaInformationsReport .getOSIconName(javaInformations.getOS()); final JLabel osLabel = new JLabel(javaInformations.getOS() + " (" + javaInformations.getAvailableProcessors() + ' ' + getString("coeurs") + ')'); if (osIconName != null) { osLabel.setIcon(ImageIconCache.getImageIcon("servers/" + osIconName)); } addJLabel(osLabel); addLabel(getString("Java")); addValue(javaInformations.getJavaVersion()); addLabel(getString("JVM")); final JLabel jvmVersionLabel = new JLabel(javaInformations.getJvmVersion()); if (javaInformations.getJvmVersion().contains("Client")) { jvmVersionLabel.setIcon(ImageIconCache.getImageIcon("alert.png")); jvmVersionLabel.setHorizontalTextPosition(SwingConstants.LEFT); jvmVersionLabel.setToolTipText(getString("Client_JVM")); } addJLabel(jvmVersionLabel); addLabel(getString("PID")); addValue(javaInformations.getPID()); final long unixOpenFileDescriptorCount = javaInformations.getUnixOpenFileDescriptorCount(); if (unixOpenFileDescriptorCount >= 0) { final long unixMaxFileDescriptorCount = javaInformations .getUnixMaxFileDescriptorCount(); addLabel(getString("nb_fichiers")); addJLabel(toBarWithAlert(integerFormat.format(unixOpenFileDescriptorCount) + " / " + integerFormat.format(unixMaxFileDescriptorCount), javaInformations.getUnixOpenFileDescriptorPercentage(), null)); // writeGraph("fileDescriptors", integerFormat.format(unixOpenFileDescriptorCount)); } writeServerInfoAndContextPath(); addLabel(getString("Demarrage")); addValue(I18N.createDateAndTimeFormat().format(javaInformations.getStartDate())); addLabel(getString("Arguments_JVM")); addValue(javaInformations.getJvmArguments()); if (javaInformations.getSessionCount() >= 0) { addLabel(getString("httpSessionsMeanAge")); // writeGraph("httpSessionsMeanAge", integerFormat.format(javaInformations.getSessionMeanAgeInMinutes())); addValue(integerFormat.format(javaInformations.getSessionMeanAgeInMinutes())); } writeTomcatInformations(javaInformations.getTomcatInformationsList()); writeMemoryInformations(javaInformations.getMemoryInformations()); if (javaInformations.getFreeDiskSpaceInTemp() >= 0) { // on considère que l'espace libre sur le disque dur est celui sur la partition du répertoire temporaire addLabel(getString("Free_disk_space")); addValue(integerFormat.format(javaInformations.getFreeDiskSpaceInTemp() / 1024 / 1024) + ' ' + getString("Mo")); } writeDatabaseVersionAndDataSourceDetails(); if (javaInformations.isDependenciesEnabled()) { addLabel(getString("Dependencies")); writeDependencies(); } makeGrid(); } private void writeServerInfoAndContextPath() { final String serverInfo = javaInformations.getServerInfo(); if (serverInfo != null) { addLabel(getString("Serveur")); final String applicationServerIconName = HtmlJavaInformationsReport .getApplicationServerIconName(serverInfo); final JLabel serverInfoLabel = new JLabel(serverInfo); if (applicationServerIconName != null) { serverInfoLabel.setIcon(ImageIconCache.getImageIcon("servers/" + applicationServerIconName)); } addJLabel(serverInfoLabel); addLabel(getString("Contexte_webapp")); addValue(javaInformations.getContextPath()); } } private void writeDatabaseVersionAndDataSourceDetails() { if (!noDatabase && javaInformations.getDataBaseVersion() != null) { addLabel(getString("Base_de_donnees")); addValue(javaInformations.getDataBaseVersion()); } if (javaInformations.getDataSourceDetails() != null) { addLabel(getString("DataSource_jdbc")); addValue(javaInformations.getDataSourceDetails()); addLabel(""); final MHyperLink dataSourceReferenceHyperLink = new MHyperLink("DataSource reference", "http://commons.apache.org/dbcp/apidocs/org/apache/commons/dbcp/BasicDataSource.html"); gridPanel.add(dataSourceReferenceHyperLink); } } private void writeTomcatInformations(List<TomcatInformations> tomcatInformationsList) { final List<TomcatInformations> list = new ArrayList<>(); for (final TomcatInformations tomcatInformations : tomcatInformationsList) { if (tomcatInformations.getRequestCount() > 0) { list.add(tomcatInformations); } } // final boolean onlyOne = list.size() == 1; final String equals = " = "; for (final TomcatInformations tomcatInformations : list) { addLabel("Tomcat " + I18N.htmlEncode(tomcatInformations.getName(), false)); // rq: on n'affiche pas pour l'instant getCurrentThreadCount final int currentThreadsBusy = tomcatInformations.getCurrentThreadsBusy(); final String value = getString("busyThreads") + equals + integerFormat.format(currentThreadsBusy) + " / " + integerFormat.format(tomcatInformations.getMaxThreads()) + '\n' + getString("bytesReceived") + equals + integerFormat.format(tomcatInformations.getBytesReceived()) + '\n' + getString("bytesSent") + equals + integerFormat.format(tomcatInformations.getBytesSent()) + '\n' + getString("requestCount") + equals + integerFormat.format(tomcatInformations.getRequestCount()) + '\n' + getString("errorCount") + equals + integerFormat.format(tomcatInformations.getErrorCount()) + '\n' + getString("processingTime") + equals + integerFormat.format(tomcatInformations.getProcessingTime()) + '\n' + getString("maxProcessingTime") + equals + integerFormat.format(tomcatInformations.getMaxTime()); final JLabel label = toBarWithAlert(value, 100d * currentThreadsBusy / tomcatInformations.getMaxThreads(), null); label.setVerticalTextPosition(SwingConstants.TOP); addJLabel(label); // if (onlyOne) { // writeGraph("tomcatBusyThreads", integerFormat.format(currentThreadsBusy)); // } // if (onlyOne) { // writeGraph("tomcatBytesReceived", // integerFormat.format(tomcatInformations.getBytesReceived())); // } // if (onlyOne) { // writeGraph("tomcatBytesSent", // integerFormat.format(tomcatInformations.getBytesSent())); // } } } private void writeMemoryInformations(MemoryInformations memoryInformations) { addLabel(getString("Gestion_memoire")); addValue(memoryInformations.getMemoryDetails().replace(" Mo", ' ' + getString("Mo"))); final long usedPermGen = memoryInformations.getUsedPermGen(); if (usedPermGen > 0) { // perm gen est à 0 sous jrockit final long maxPermGen = memoryInformations.getMaxPermGen(); addLabel(getString("Memoire_Perm_Gen")); final String permGen = integerFormat.format(usedPermGen / 1024 / 1024) + ' ' + getString("Mo"); if (maxPermGen > 0) { addJLabel(toBarWithAlert( permGen + " / " + integerFormat.format(maxPermGen / 1024 / 1024) + ' ' + getString("Mo"), memoryInformations.getUsedPermGenPercentage(), "-XX:MaxPermSize")); } else { addValue(permGen); } } } private void writeDependencies() { final int nbDependencies = javaInformations.getDependenciesList().size(); final JPanel panel = new JPanel(new BorderLayout()); panel.setOpaque(false); final JLabel nbDependenciesLabel = new JLabel(getFormattedString("nb_dependencies", nbDependencies)); panel.add(nbDependenciesLabel, BorderLayout.CENTER); if (nbDependencies > 0) { nbDependenciesLabel.setText(nbDependenciesLabel.getText() + " ; "); final JPanel buttonsPanel = new JPanel(new BorderLayout()); buttonsPanel.setOpaque(false); final MButton detailsButton = new MButton(getString("Details"), PLUS_ICON); buttonsPanel.add(detailsButton, BorderLayout.WEST); if (javaInformations.doesPomXmlExists() && Parameters.isSystemActionsEnabled()) { final MButton pomXmlButton = new MButton(getString("pom.xml"), XML_ICON); buttonsPanel.add(pomXmlButton, BorderLayout.EAST); pomXmlButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { Desktop.getDesktop().browse( new URI(getMonitoringUrl().toExternalForm() + "?part=pom.xml")); } catch (final Exception ex) { showException(ex); } } }); } panel.add(buttonsPanel, BorderLayout.EAST); final JLabel dependenciesLabel = new JLabel( replaceLineFeedWithHtmlBr(javaInformations.getDependencies())); dependenciesLabel.setVisible(false); panel.add(dependenciesLabel, BorderLayout.SOUTH); final JPanel localGridPanel = gridPanel; detailsButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { dependenciesLabel.setVisible(!dependenciesLabel.isVisible()); localGridPanel.validate(); if (detailsButton.getIcon() == PLUS_ICON) { detailsButton.setIcon(MINUS_ICON); } else { detailsButton.setIcon(PLUS_ICON); } } }); } gridPanel.add(panel); } private void makeGrid() { SpringUtilities.makeCompactGrid(gridPanel, gridPanel.getComponentCount() / 2, 2, 0, 0, 10, 5); } private void addLabel(String text) { final String tmp = replaceLineFeedWithHtmlBr(text); final JLabel label = new JLabel(tmp + ": "); label.setVerticalAlignment(SwingConstants.TOP); addJLabel(label); } private void addValue(String value) { final String tmp = replaceLineFeedWithHtmlBr(value); addJLabel(new JLabel(tmp)); } private void addJLabel(JLabel jLabel) { gridPanel.add(jLabel); } static JLabel toBar(String text, double percentValue) { final String tmp = replaceLineFeedWithHtmlBr(text); final JLabel label = new JLabel(tmp); label.setIconTextGap(10); try { label.setIcon(new ImageIcon(Bar.toBar(percentValue))); } catch (final IOException e) { throw new IllegalStateException(e); } label.setHorizontalTextPosition(SwingConstants.LEFT); final double myPercent = Math.max(Math.min(percentValue, 100d), 0d); label.setToolTipText(I18N.createPercentFormat().format(myPercent) + '%'); return label; } private static JLabel toBarWithAlert(String text, double percentValue, String configurationDetail) { final JLabel label = toBar(text, percentValue); if (percentValue >= JavaInformations.HIGH_USAGE_THRESHOLD_IN_PERCENTS) { try { label.setIcon(new ImageIcon(Bar.toBarWithAlert(percentValue))); } catch (final IOException e) { throw new IllegalStateException(e); } String toolTipText = label.getToolTipText(); toolTipText = "<html>" + toolTipText + "<br/>" + getString("High_usage"); if (configurationDetail != null) { toolTipText += " (" + configurationDetail + ')'; } label.setToolTipText(toolTipText); } return label; } private static String replaceLineFeedWithHtmlBr(String text) { if (text.indexOf('\n') != -1) { // JLabel accepte la syntaxe html return "<html>" + text.replace("\n", "<br/>"); } return text; } URL getMonitoringUrl() { return monitoringUrl; } }