1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package org.apache.jmeter.reporters; 20 21 import java.awt.BorderLayout; 22 import java.awt.Color; 23 import java.awt.Graphics; 24 import java.awt.GridBagConstraints; 25 import java.awt.GridBagLayout; 26 import java.awt.Insets; 27 import java.io.BufferedReader; 28 import java.io.File; 29 import java.io.FileReader; 30 import java.io.IOException; 31 import java.text.DecimalFormat; 32 import java.util.Enumeration; 33 import java.util.Hashtable; 34 import java.util.Vector; 35 36 import javax.swing.JFrame; 37 import javax.swing.JLabel; 38 import javax.swing.JOptionPane; 39 import javax.swing.JPanel; 40 41 import org.apache.jorphan.logging.LoggingManager; 42 import org.apache.log.Logger; 43 44 /** 45 * This class loads data from a saved file and displays statistics about it. 46 * 47 * 48 * @version $Revision: 768439 $ 49 */ 50 public class FileReporter extends JPanel { 51 private static final Logger log = LoggingManager.getLoggerForClass(); 52 53 private final Hashtable data = new Hashtable(); 54 55 /** initalize a file reporter from a file */ 56 public void init(String file) throws IOException { 57 File datafile = new File(file); 58 BufferedReader reader = null; 59 60 try { 61 if (datafile.canRead()) { 62 reader = new BufferedReader(new FileReader(datafile)); 63 } else { 64 JOptionPane.showMessageDialog(null, "The file you specified cannot be read.", "Information", 65 JOptionPane.INFORMATION_MESSAGE); 66 return; 67 } 68 String line; 69 70 while ((line = reader.readLine()) != null) { 71 try { 72 line = line.trim(); 73 if (line.startsWith("#") || line.length() == 0) { 74 continue; 75 } 76 int splitter = line.lastIndexOf(' '); 77 String key = line.substring(0, splitter); 78 int len = line.length() - 1; 79 Integer value = null; 80 81 if (line.charAt(len) == ',') { 82 value = new Integer(line.substring(splitter + 1, len)); 83 } else { 84 value = new Integer(line.substring(splitter + 1)); 85 } 86 Vector v = getData(key); 87 88 if (v == null) { 89 v = new Vector(); 90 this.data.put(key, v); 91 } 92 v.addElement(value); 93 } catch (NumberFormatException nfe) { 94 log.error("This line could not be parsed: " + line, nfe); 95 } catch (Exception e) { 96 log.error("This line caused a problem: " + line, e); 97 } 98 } 99 } finally { 100 if (reader != null) 101 reader.close(); 102 } 103 showPanel(); 104 } 105 106 public Vector getData(String key) { 107 return (Vector) data.get(key); 108 } 109 110 /** 111 * Show main panel with length, graph, and stats. 112 */ 113 public void showPanel() { 114 JFrame f = new JFrame("Data File Report"); 115 116 setLayout(new BorderLayout()); 117 GraphPanel gp = new GraphPanel(data); 118 119 add(gp, "Center"); 120 add(gp.getStats(), BorderLayout.EAST); 121 add(gp.getLegend(), BorderLayout.NORTH); 122 f.setSize(500, 300); 123 f.getContentPane().add(this); 124 f.show(); 125 } 126 127 /** 128 * Graph panel generates all the panels for this reporter. Data is organized 129 * based on thread name in a hashtable. The data itself is a Vector of Integer 130 * objects 131 */ 132 private static class GraphPanel extends JPanel { 133 // boolean autoScale = true; 134 Hashtable data; 135 136 Vector keys = new Vector(); 137 138 Vector colorList = new Vector(); 139 140 public GraphPanel(Hashtable data) { 141 this.data = data; 142 Enumeration e = data.keys(); 143 144 while (e.hasMoreElements()) { 145 String key = (String) e.nextElement(); 146 147 keys.addElement(key); 148 } 149 for (int a = 0x33; a < 0xFF; a += 0x66) { 150 for (int b = 0x33; b < 0xFF; b += 0x66) { 151 for (int c = 0x33; c < 0xFF; c += 0x66) { 152 colorList.addElement(new Color(a, b, c)); 153 } 154 } 155 } 156 } 157 158 /** 159 * Get the maximum for all the data. 160 */ 161 public float getMax() { 162 float maxValue = 0; 163 164 for (int t = 0; t < keys.size(); t++) { 165 String key = (String) keys.elementAt(t); 166 Vector temp = (Vector) data.get(key); 167 168 for (int j = 0; j < temp.size(); j++) { 169 float f = ((Integer) temp.elementAt(j)).intValue(); 170 171 maxValue = Math.max(f, maxValue); 172 } 173 } 174 return (float) (maxValue + maxValue * 0.1); 175 } 176 177 /** 178 * Get the minimum for all the data. 179 */ 180 public float getMin() { 181 float minValue = 9999999; 182 183 for (int t = 0; t < keys.size(); t++) { 184 String key = (String) keys.elementAt(t); 185 Vector temp = (Vector) data.get(key); 186 187 for (int j = 0; j < temp.size(); j++) { 188 float f = ((Integer) temp.elementAt(j)).intValue(); 189 190 minValue = Math.min(f, minValue); 191 } 192 } 193 return (float) (minValue - minValue * 0.1); 194 } 195 196 /** 197 * Get the legend panel. 198 */ 199 public JPanel getLegend() { 200 JPanel main = new JPanel(); 201 GridBagLayout g = new GridBagLayout(); 202 203 main.setLayout(g); 204 GridBagConstraints c = new GridBagConstraints(); 205 206 c.insets = new Insets(3, 3, 3, 3); 207 c.fill = GridBagConstraints.BOTH; 208 c.gridwidth = 1; 209 c.gridheight = 1; 210 for (int t = 0; t < keys.size(); t++) { 211 String key = (String) keys.elementAt(t); 212 JLabel colorSwatch = new JLabel(" "); 213 214 colorSwatch.setBackground((Color) colorList.elementAt(t % colorList.size())); 215 colorSwatch.setOpaque(true); 216 c.gridx = 1; 217 c.gridy = t; 218 g.setConstraints(colorSwatch, c); 219 main.add(colorSwatch); 220 JLabel name = new JLabel(key); 221 222 c.gridx = 2; 223 c.gridy = t; 224 g.setConstraints(name, c); 225 main.add(name); 226 } 227 return main; 228 } 229 230 /** 231 * Get the stats panel. 232 */ 233 public JPanel getStats() { 234 int total = 0; 235 float totalValue = 0; 236 float maxValue = 0; 237 float minValue = 999999; 238 239 for (int t = 0; t < keys.size(); t++) { 240 String key = (String) keys.elementAt(t); 241 Vector temp = (Vector) data.get(key); 242 243 for (int j = 0; j < temp.size(); j++) { 244 float f = ((Integer) temp.elementAt(j)).intValue(); 245 246 minValue = Math.min(f, minValue); 247 maxValue = Math.max(f, maxValue); 248 totalValue += f; 249 total++; 250 } 251 } 252 float averageValue = totalValue / total; 253 JPanel main = new JPanel(); 254 GridBagLayout g = new GridBagLayout(); 255 256 main.setLayout(g); 257 DecimalFormat df = new DecimalFormat("#0.0"); 258 GridBagConstraints c = new GridBagConstraints(); 259 260 c.insets = new Insets(3, 6, 3, 6); 261 c.fill = GridBagConstraints.BOTH; 262 c.gridwidth = 1; 263 c.gridheight = 1; 264 JLabel count = new JLabel("Count: " + total); 265 266 c.gridx = 1; 267 c.gridy = 1; 268 g.setConstraints(count, c); 269 JLabel min = new JLabel("Min: " + df.format(new Float(minValue))); 270 271 c.gridx = 1; 272 c.gridy = 2; 273 g.setConstraints(min, c); 274 JLabel max = new JLabel("Max: " + df.format(new Float(maxValue))); 275 276 c.gridx = 1; 277 c.gridy = 3; 278 g.setConstraints(max, c); 279 JLabel average = new JLabel("Average: " + df.format(new Float(averageValue))); 280 281 c.gridx = 1; 282 c.gridy = 4; 283 g.setConstraints(average, c); 284 main.add(count); 285 main.add(min); 286 main.add(max); 287 main.add(average); 288 return main; 289 } 290 291 /** 292 * Gets the size of the biggest Vector. 293 */ 294 public int getDataWidth() { 295 int size = 0; 296 297 for (int t = 0; t < keys.size(); t++) { 298 String key = (String) keys.elementAt(t); 299 Vector v = (Vector) data.get(key); 300 301 size = Math.max(size, v.size()); 302 } 303 return size; 304 } 305 306 /** 307 * Draws the graph. 308 */ 309 public void update(Graphics g) { 310 // setup drawing area 311 int base = 10; 312 313 g.setColor(Color.white); 314 g.fillRect(0, 0, getSize().width, getSize().height); 315 int width = getSize().width; 316 int height = getSize().height; 317 float maxValue = getMax(); 318 float minValue = getMin(); 319 320 // draw grid 321 g.setColor(Color.gray); 322 int dataWidth = getDataWidth(); 323 int increment = Math.round((float)(width - 1) / (dataWidth - 1)); 324 325 /* 326 * for (int t = 0; t < dataWidth; t++) { g.drawLine(t * increment, 0, t * 327 * increment, height); } 328 */ 329 int yIncrement = Math.round(((float) height - (1 + base)) / (10 - 1)); 330 331 /* 332 * for (int t = 0; t < 10; t++) { g.drawLine(0, height - t * yIncrement, 333 * width, height - t * yIncrement); } 334 */ 335 // draw axis 336 for (int t = 1; t < dataWidth; t += (dataWidth / 25 + 1)) { 337 g.drawString((new Integer(t)).toString(), t * increment + 2, height - 2); 338 } 339 float incrementValue = (maxValue - minValue) / (10 - 1); 340 341 for (int t = 0; t < 10; t++) { 342 g.drawString(new Integer(Math.round(minValue + (t * incrementValue))).toString(), 2, height - t 343 * yIncrement - 2 - base); 344 } 345 // draw data lines 346 int start = 0; 347 348 for (int t = 0; t < keys.size(); t++) { 349 String key = (String) keys.elementAt(t); 350 Vector v = (Vector) data.get(key); 351 352 start = 0; 353 g.setColor((Color) colorList.elementAt(t % colorList.size())); 354 for (int i = 0; i < v.size() - 1; i++) { 355 float y1 = ((Integer) v.elementAt(i)).intValue(); 356 float y2 = ((Integer) v.elementAt(i + 1)).intValue(); 357 358 y1 = y1 - minValue; 359 y2 = y2 - minValue; 360 int Y1 = Math.round((height * y1) / (maxValue - minValue)); 361 int Y2 = Math.round((height * y2) / (maxValue - minValue)); 362 363 Y1 = height - Y1 - base; 364 Y2 = height - Y2 - base; 365 g.drawLine(start, Y1, start + increment, Y2); 366 367 start += increment; 368 } 369 } 370 } 371 372 public void paint(Graphics g) { 373 update(g); 374 } 375 } 376 }