| 1 | |
package kg.apc.jmeter.vizualizers; |
| 2 | |
|
| 3 | |
|
| 4 | |
import java.awt.BorderLayout; |
| 5 | |
import java.awt.Color; |
| 6 | |
import java.awt.Component; |
| 7 | |
import java.awt.Dimension; |
| 8 | |
import java.awt.Frame; |
| 9 | |
import java.awt.GraphicsEnvironment; |
| 10 | |
import java.awt.Insets; |
| 11 | |
import java.awt.event.ActionEvent; |
| 12 | |
import java.awt.event.ActionListener; |
| 13 | |
import java.text.SimpleDateFormat; |
| 14 | |
import java.util.Arrays; |
| 15 | |
import java.util.LinkedList; |
| 16 | |
import java.util.List; |
| 17 | |
import javax.swing.BorderFactory; |
| 18 | |
import javax.swing.DefaultCellEditor; |
| 19 | |
import javax.swing.JButton; |
| 20 | |
import javax.swing.JComboBox; |
| 21 | |
import javax.swing.JDialog; |
| 22 | |
import javax.swing.JMenuItem; |
| 23 | |
import javax.swing.JPanel; |
| 24 | |
import javax.swing.JPopupMenu; |
| 25 | |
import javax.swing.JScrollPane; |
| 26 | |
import javax.swing.JTable; |
| 27 | |
import javax.swing.JTextArea; |
| 28 | |
import javax.swing.JTextField; |
| 29 | |
import javax.swing.ListSelectionModel; |
| 30 | |
import kg.apc.charting.AbstractGraphRow; |
| 31 | |
import kg.apc.jmeter.JMeterPluginsUtils; |
| 32 | |
import kg.apc.jmeter.graphs.AbstractOverTimeVisualizer; |
| 33 | |
import kg.apc.jmeter.gui.ButtonPanelAddCopyRemove; |
| 34 | |
import kg.apc.jmeter.gui.ComponentBorder; |
| 35 | |
import kg.apc.jmeter.gui.DialogFactory; |
| 36 | |
import kg.apc.jmeter.gui.GuiBuilderHelper; |
| 37 | |
import kg.apc.jmeter.perfmon.PerfMonCollector; |
| 38 | |
import kg.apc.jmeter.perfmon.PerfMonSampleResult; |
| 39 | |
import org.apache.jmeter.gui.GuiPackage; |
| 40 | |
import org.apache.jmeter.gui.util.PowerTableModel; |
| 41 | |
import org.apache.jmeter.samplers.SampleResult; |
| 42 | |
import org.apache.jmeter.testelement.TestElement; |
| 43 | |
import org.apache.jmeter.testelement.property.CollectionProperty; |
| 44 | |
import org.apache.jmeter.testelement.property.JMeterProperty; |
| 45 | |
import org.apache.jmeter.testelement.property.NullProperty; |
| 46 | |
import org.apache.jorphan.logging.LoggingManager; |
| 47 | |
import org.apache.log.Logger; |
| 48 | |
|
| 49 | 0 | public class PerfMonGui |
| 50 | |
extends AbstractOverTimeVisualizer { |
| 51 | |
|
| 52 | 1 | public static final List<String> metrics = Arrays.asList("CPU", "Memory", "Swap", "Disks I/O", "Network I/O"); |
| 53 | 1 | private static final Logger log = LoggingManager.getLoggerForClass(); |
| 54 | |
private PowerTableModel tableModel; |
| 55 | |
private JTable grid; |
| 56 | |
private JTextArea errorTextArea; |
| 57 | |
private JScrollPane errorPane; |
| 58 | 1 | public static final String[] columnIdentifiers = new String[]{ |
| 59 | |
"Host / IP", "Port", "Metric to collect", "Metric parameter (see help)" |
| 60 | |
}; |
| 61 | 1 | public static final Class[] columnClasses = new Class[]{ |
| 62 | |
String.class, String.class, String.class, String.class |
| 63 | |
}; |
| 64 | 1 | private static String[] defaultValues = new String[]{ |
| 65 | |
"localhost", "4444", "CPU", "" |
| 66 | |
}; |
| 67 | |
|
| 68 | |
public PerfMonGui() { |
| 69 | 12 | super(); |
| 70 | 12 | setGranulation(1000); |
| 71 | 12 | graphPanel.getGraphObject().setYAxisLabel("Performance Metrics"); |
| 72 | 12 | graphPanel.getGraphObject().getChartSettings().setExpendRows(true); |
| 73 | 12 | } |
| 74 | |
|
| 75 | |
@Override |
| 76 | |
protected JSettingsPanel createSettingsPanel() { |
| 77 | 13 | return new JSettingsPanel(this, |
| 78 | |
JSettingsPanel.GRADIENT_OPTION |
| 79 | |
| JSettingsPanel.LIMIT_POINT_OPTION |
| 80 | |
| JSettingsPanel.MAXY_OPTION |
| 81 | |
| JSettingsPanel.RELATIVE_TIME_OPTION |
| 82 | |
| JSettingsPanel.AUTO_EXPAND_OPTION |
| 83 | |
| JSettingsPanel.MARKERS_OPTION_DISABLED); |
| 84 | |
} |
| 85 | |
|
| 86 | |
@Override |
| 87 | |
public String getWikiPage() { |
| 88 | 15 | return "PerfMon"; |
| 89 | |
} |
| 90 | |
|
| 91 | |
@Override |
| 92 | |
public String getLabelResource() { |
| 93 | 1 | return getClass().getSimpleName(); |
| 94 | |
} |
| 95 | |
|
| 96 | |
@Override |
| 97 | |
public String getStaticLabel() { |
| 98 | 25 | return JMeterPluginsUtils.prefixLabel("PerfMon Metrics Collector"); |
| 99 | |
} |
| 100 | |
|
| 101 | |
@Override |
| 102 | |
protected JPanel getGraphPanelContainer() { |
| 103 | 13 | JPanel panel = new JPanel(new BorderLayout()); |
| 104 | 13 | JPanel innerTopPanel = new JPanel(new BorderLayout()); |
| 105 | |
|
| 106 | 13 | errorPane = new JScrollPane(); |
| 107 | 13 | errorPane.setMinimumSize(new Dimension(100, 50)); |
| 108 | 13 | errorPane.setPreferredSize(new Dimension(100, 50)); |
| 109 | |
|
| 110 | 13 | errorTextArea = new JTextArea(); |
| 111 | 13 | errorTextArea.setForeground(Color.red); |
| 112 | 13 | errorTextArea.setBackground(new Color(255, 255, 153)); |
| 113 | 13 | errorTextArea.setEditable(false); |
| 114 | 13 | errorPane.setViewportView(errorTextArea); |
| 115 | |
|
| 116 | 13 | registerPopup(); |
| 117 | |
|
| 118 | 13 | innerTopPanel.add(createConnectionsPanel(), BorderLayout.NORTH); |
| 119 | 13 | innerTopPanel.add(errorPane, BorderLayout.SOUTH); |
| 120 | 13 | innerTopPanel.add(getFilePanel(), BorderLayout.CENTER); |
| 121 | |
|
| 122 | 13 | panel.add(innerTopPanel, BorderLayout.NORTH); |
| 123 | |
|
| 124 | 13 | errorPane.setVisible(false); |
| 125 | |
|
| 126 | 13 | return panel; |
| 127 | |
} |
| 128 | |
|
| 129 | |
private void addErrorMessage(String msg, long time) { |
| 130 | 0 | errorPane.setVisible(true); |
| 131 | 0 | SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); |
| 132 | 0 | String newLine = ""; |
| 133 | 0 | if (errorTextArea.getText().length() != 0) { |
| 134 | 0 | newLine = "\n"; |
| 135 | |
} |
| 136 | 0 | errorTextArea.setText(errorTextArea.getText() + newLine + formatter.format(time) + " - ERROR: " + msg); |
| 137 | 0 | errorTextArea.setCaretPosition(errorTextArea.getDocument().getLength()); |
| 138 | 0 | updateGui(); |
| 139 | 0 | } |
| 140 | |
|
| 141 | |
public void clearErrorMessage() { |
| 142 | 2 | errorTextArea.setText(""); |
| 143 | 2 | errorPane.setVisible(false); |
| 144 | 2 | } |
| 145 | |
|
| 146 | |
private void registerPopup() { |
| 147 | 13 | JPopupMenu popup = new JPopupMenu(); |
| 148 | 13 | JMenuItem hideMessagesMenu = new JMenuItem("Hide Error Panel"); |
| 149 | 13 | hideMessagesMenu.addActionListener(new HideAction()); |
| 150 | 13 | popup.add(hideMessagesMenu); |
| 151 | 13 | errorTextArea.setComponentPopupMenu(popup); |
| 152 | 13 | } |
| 153 | |
|
| 154 | |
@Override |
| 155 | |
public void clearData() { |
| 156 | 1 | clearErrorMessage(); |
| 157 | 1 | super.clearData(); |
| 158 | 1 | } |
| 159 | |
|
| 160 | |
private Component createConnectionsPanel() { |
| 161 | 13 | JPanel panel = new JPanel(new BorderLayout(5, 5)); |
| 162 | 13 | panel.setBorder(BorderFactory.createTitledBorder("Servers to Monitor (ServerAgent must be started, see help)")); |
| 163 | 13 | panel.setPreferredSize(new Dimension(150, 150)); |
| 164 | |
|
| 165 | 13 | JScrollPane scroll = new JScrollPane(createGrid()); |
| 166 | 13 | scroll.setPreferredSize(scroll.getMinimumSize()); |
| 167 | 13 | panel.add(scroll, BorderLayout.CENTER); |
| 168 | 13 | panel.add(new ButtonPanelAddCopyRemove(grid, tableModel, defaultValues), BorderLayout.SOUTH); |
| 169 | |
|
| 170 | 13 | List<String> items = new LinkedList<String>(metrics); |
| 171 | |
|
| 172 | 13 | items.add("TCP"); |
| 173 | 13 | items.add("JMX"); |
| 174 | 13 | items.add("EXEC"); |
| 175 | 13 | items.add("TAIL"); |
| 176 | 13 | JComboBox metricTypesBox = new JComboBox(items.toArray()); |
| 177 | 13 | grid.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(metricTypesBox)); |
| 178 | |
|
| 179 | 13 | final JTextField wizEditor = new JTextField(); |
| 180 | 13 | wizEditor.setBorder(null); |
| 181 | 13 | JButton wiz = new JButton("..."); |
| 182 | 13 | if (!GraphicsEnvironment.isHeadless()) { |
| 183 | 13 | wiz.addActionListener(new java.awt.event.ActionListener() { |
| 184 | |
@Override |
| 185 | |
public void actionPerformed(java.awt.event.ActionEvent evt) { |
| 186 | 0 | Frame parent = GuiPackage.getInstance().getMainFrame(); |
| 187 | 0 | String type = grid.getValueAt(grid.getSelectedRow(), 2).toString(); |
| 188 | |
|
| 189 | 0 | JPerfmonParamsPanel dlgContent = new JPerfmonParamsPanel(type, wizEditor); |
| 190 | 0 | dlgContent.setMinWidth(400); |
| 191 | 0 | JDialog dlg = DialogFactory.getJDialogInstance(parent, "PerfMon [" + type + "] Parameters Helper", |
| 192 | |
true, dlgContent, "/kg/apc/jmeter/vizualizers/wand.png"); |
| 193 | |
|
| 194 | 0 | DialogFactory.centerDialog(parent, dlg); |
| 195 | |
|
| 196 | 0 | dlg.setVisible(true); |
| 197 | 0 | } |
| 198 | |
}); |
| 199 | |
} |
| 200 | 13 | wiz.setMargin(new Insets(0, 6, 5, 6)); |
| 201 | 13 | GuiBuilderHelper.strechItemToComponent(wizEditor, wiz); |
| 202 | 13 | ComponentBorder bd = new ComponentBorder(wiz); |
| 203 | |
|
| 204 | 13 | bd.install(wizEditor); |
| 205 | |
|
| 206 | 13 | grid.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(wizEditor)); |
| 207 | 13 | grid.getTableHeader().setReorderingAllowed(false); |
| 208 | |
|
| 209 | 13 | return panel; |
| 210 | |
} |
| 211 | |
|
| 212 | |
private JTable createGrid() { |
| 213 | 13 | grid = new JTable(); |
| 214 | 13 | createTableModel(); |
| 215 | 13 | grid.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
| 216 | 13 | grid.setMinimumSize(new Dimension(200, 100)); |
| 217 | |
|
| 218 | 13 | grid.getColumnModel().getColumn(0).setPreferredWidth(170); |
| 219 | 13 | grid.getColumnModel().getColumn(1).setPreferredWidth(80); |
| 220 | 13 | grid.getColumnModel().getColumn(2).setPreferredWidth(120); |
| 221 | 13 | grid.getColumnModel().getColumn(3).setPreferredWidth(500); |
| 222 | |
|
| 223 | 13 | return grid; |
| 224 | |
} |
| 225 | |
|
| 226 | |
private void createTableModel() { |
| 227 | 13 | tableModel = new PowerTableModel(columnIdentifiers, columnClasses); |
| 228 | 13 | grid.setModel(tableModel); |
| 229 | 13 | } |
| 230 | |
|
| 231 | |
@Override |
| 232 | |
public TestElement createTestElement() { |
| 233 | 2 | TestElement te = new PerfMonCollector(); |
| 234 | 2 | modifyTestElement(te); |
| 235 | 2 | te.setComment(JMeterPluginsUtils.getWikiLinkText(getWikiPage())); |
| 236 | 2 | return te; |
| 237 | |
} |
| 238 | |
|
| 239 | |
@Override |
| 240 | |
public void modifyTestElement(TestElement te) { |
| 241 | 3 | super.modifyTestElement(te); |
| 242 | 3 | if (grid.isEditing()) { |
| 243 | 0 | grid.getCellEditor().stopCellEditing(); |
| 244 | |
} |
| 245 | |
|
| 246 | 3 | if (te instanceof PerfMonCollector) { |
| 247 | 3 | PerfMonCollector pmte = (PerfMonCollector) te; |
| 248 | 3 | CollectionProperty rows = JMeterPluginsUtils.tableModelRowsToCollectionProperty(tableModel, PerfMonCollector.DATA_PROPERTY); |
| 249 | 3 | pmte.setData(rows); |
| 250 | |
} |
| 251 | 3 | super.configureTestElement(te); |
| 252 | 3 | } |
| 253 | |
|
| 254 | |
@Override |
| 255 | |
public void configure(TestElement te) { |
| 256 | 1 | super.configure(te); |
| 257 | 1 | PerfMonCollector pmte = (PerfMonCollector) te; |
| 258 | 1 | JMeterProperty perfmonValues = pmte.getMetricSettings(); |
| 259 | 1 | if (!(perfmonValues instanceof NullProperty)) { |
| 260 | 0 | JMeterPluginsUtils.collectionPropertyToTableModelRows((CollectionProperty) perfmonValues, tableModel); |
| 261 | |
} else { |
| 262 | 1 | log.warn("Received null property instead of collection"); |
| 263 | |
} |
| 264 | 1 | } |
| 265 | |
|
| 266 | |
@Override |
| 267 | |
public void add(SampleResult res) { |
| 268 | 1 | if (res.isSuccessful()) { |
| 269 | 1 | if (isSampleIncluded(res)) { |
| 270 | 1 | super.add(res); |
| 271 | 1 | addPerfMonRecord(res.getSampleLabel(), normalizeTime(res.getStartTime()), PerfMonSampleResult.getValue(res)); |
| 272 | 1 | updateGui(null); |
| 273 | |
} |
| 274 | |
} else { |
| 275 | 0 | addErrorMessage(res.getResponseMessage(), res.getStartTime()); |
| 276 | |
} |
| 277 | 1 | } |
| 278 | |
|
| 279 | |
private void addPerfMonRecord(String rowName, long time, double value) { |
| 280 | 1 | AbstractGraphRow row = model.get(rowName); |
| 281 | 1 | if (row == null) { |
| 282 | 1 | row = getNewRow(model, AbstractGraphRow.ROW_AVERAGES, rowName, |
| 283 | |
AbstractGraphRow.MARKER_SIZE_NONE, false, false, false, true, true); |
| 284 | |
} |
| 285 | 1 | row.add(time, value); |
| 286 | 1 | } |
| 287 | |
|
| 288 | 26 | private class HideAction |
| 289 | |
implements ActionListener { |
| 290 | |
|
| 291 | |
@Override |
| 292 | |
public void actionPerformed(ActionEvent e) { |
| 293 | 0 | errorPane.setVisible(false); |
| 294 | 0 | updateGui(); |
| 295 | 0 | } |
| 296 | |
} |
| 297 | |
} |