You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by wo...@apache.org on 2004/05/28 04:35:12 UTC

cvs commit: jakarta-jmeter/src/components/org/apache/jmeter/visualizers DistributionGraph.java DistributionGraphVisualizer.java GraphModel.java

woolfel     2004/05/27 19:35:12

  Modified:    src/components/org/apache/jmeter/visualizers GraphModel.java
  Added:       src/components/org/apache/jmeter/visualizers
                        DistributionGraph.java
                        DistributionGraphVisualizer.java
  Log:
  checking in the changes for the new Distribution Graph. I've left the
  title as "alpha" for now.
  
  Revision  Changes    Path
  1.15      +6 -2      jakarta-jmeter/src/components/org/apache/jmeter/visualizers/GraphModel.java
  
  Index: GraphModel.java
  ===================================================================
  RCS file: /home/cvs/jakarta-jmeter/src/components/org/apache/jmeter/visualizers/GraphModel.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- GraphModel.java	13 Feb 2004 01:48:46 -0000	1.14
  +++ GraphModel.java	28 May 2004 02:35:12 -0000	1.15
  @@ -301,4 +301,8 @@
           samples.add(s);
           return s;
       }
  +    
  +    public StatCalculator getStatCalc(){
  +    	return this.statCalc;
  +    }
   }
  
  
  
  1.1                  jakarta-jmeter/src/components/org/apache/jmeter/visualizers/DistributionGraph.java
  
  Index: DistributionGraph.java
  ===================================================================
  // $Header: 
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   *
   * 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 org.apache.jmeter.visualizers;
  
  import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.Graphics;
  import java.awt.Rectangle;
  import java.util.Arrays;
  import java.util.Collection;
  
  import javax.swing.JComponent;
  import javax.swing.Scrollable;
  import javax.swing.SwingUtilities;
  
  import org.apache.jmeter.samplers.Clearable;
  import org.apache.jorphan.logging.LoggingManager;
  import org.apache.log.Logger;
  import org.apache.jorphan.math.NumberComparator;
  import org.apache.jorphan.math.StatCalculator;
  
  /**
   * New graph for drawing distribution graph of the results. It is
   * intended as a way to view the data after the stress has been
   * performed. Although it can be used at runtime, it is not
   * recommended, since it is rather intensive.
   * The graph will draw a red line at 90% and an orange line at
   * 50%. I like distribution graphs because they allow me to see
   * how the data clumps. In general, the data will tend to clump
   * in predictable ways when the application is well designed
   * and implemented. Data that generates erratic graphs are
   * generally not desirable.
   *
   */
  public class DistributionGraph
      extends JComponent
      implements Scrollable, GraphListener, Clearable
  {
      private static Logger log = LoggingManager.getLoggerForClass();
  
      private GraphModel model;
      private static int width = 600;
      private int xborder = 30;
      
      /**
       * the granularity for the distribution
       * graph. it can only be whole numbers.
       */
      private int granularity = 5;
      /**
       * there's an option to delay drawing
       */
      private boolean delay = false;
      /**
       * delay redraw
       */
      private int counter = 20;
      private static int total = -1;
  
      /**
       * Constructor for the Graph object.
       */
      public DistributionGraph()
      {
      	init();
      }
  
      /**
       * Constructor for the Graph object.
       */
      public DistributionGraph(GraphModel model)
      {
          this();
          setModel(model);
      }
  
  	public void init(){
  		repaint();
  	}
  	
  	/**
  	 * Gets the ScrollableTracksViewportWidth attribute of the Graph object.
  	 *
  	 * @return    the ScrollableTracksViewportWidth value
  	 */
  	public boolean getScrollableTracksViewportWidth()
  	{
  		return true;
  	}
  
  	/**
  	 * Gets the ScrollableTracksViewportHeight attribute of the Graph object.
  	 *
  	 * @return    the ScrollableTracksViewportHeight value
  	 */
  	public boolean getScrollableTracksViewportHeight()
  	{
  		return true;
  	}
  
      /**
       * Sets the Model attribute of the Graph object.
       */
      private void setModel(Object model)
      {
          this.model = (GraphModel) model;
          repaint();
      }
  
      /**
       * Gets the PreferredScrollableViewportSize attribute of the Graph object.
       *
       * @return the PreferredScrollableViewportSize value
       */
      public Dimension getPreferredScrollableViewportSize()
      {
          return this.getPreferredSize();
      }
  
      /**
       * Gets the ScrollableUnitIncrement attribute of the Graph object.
       *@return              the ScrollableUnitIncrement value
       */
      public int getScrollableUnitIncrement(
          Rectangle visibleRect,
          int orientation,
          int direction)
      {
          return 5;
      }
  
      /**
       * Gets the ScrollableBlockIncrement attribute of the Graph object.
       * @return              the ScrollableBlockIncrement value
       */
      public int getScrollableBlockIncrement(
          Rectangle visibleRect,
          int orientation,
          int direction)
      {
          return (int) (visibleRect.width * .9);
      }
  
      /**
       * Clears this graph.
       */
      public void clear()
      {}
  
  	/**
  	 * method simply calls repaint()
  	 */
      public void updateGui()
      {
          repaint();
      }
  
  	/**
  	 * updateGui is called by GraphModel. Unlike Graph
  	 * class, distribution graph can delay drawing
  	 * the graph.
  	 */
      public void updateGui(final Sample oneSample)
      {
          final GraphModel m = this.model;
          SwingUtilities.invokeLater(new Runnable()
          {
              public void run()
              {
                  Graphics g = getGraphics();
  
                  if (g != null)
                  {
                  	synchronized(m){
  						drawSample(m, g);
                  	}
                  }
              }
          });
      }
  
      public void paintComponent(Graphics g)
      {
          super.paintComponent(g);
          final GraphModel m = this.model;
          synchronized (m)
          {
          	drawSample(m, g);
          }
      }
  
      private void drawSample(GraphModel model, Graphics g)
      {
          width = getWidth();
          double height = (double)getHeight() - 1.0;
  
          // first lets draw the grid
          for (int y=0; y < 4; y++){
  			int q1 = (int)(height - (height * 0.25 * y));
  			g.setColor(Color.lightGray);
  			g.drawLine(xborder,q1,width,q1);
  			g.setColor(Color.black);
  			g.drawString(String.valueOf((25 * y) + "%"),0,q1);
          }
          g.setColor(Color.black);
          // draw the X axis
          g.drawLine(xborder,(int)height,width,(int)height);
          // draw the Y axis
          g.drawLine(xborder,0,xborder,(int)height);
          // the test plan has to have more than 200 samples
          // for it to generate half way decent distribution
          // graph. the larger the sample, the better the
          // results.
          if (model != null && model.getSampleCount() > 50){
  			// now draw the bar chart
  			StatCalculator sc = model.getStatCalc();
  			Number ninety = sc.getPercentPoint(0.90);
  			Number fifty = sc.getPercentPoint(0.50);
  
  			total = sc.getCount();
  			Collection values = sc.getDistribution().values();
  			Object[] objval = new Object[values.size()];
  			objval = values.toArray(objval);
  			// we sort the objects
  			Arrays.sort(objval,new NumberComparator());
  			int len = objval.length;
  			for (int count=0; count < len; count++){
  				// calculate the height
  				Number[] num = (Number[])objval[count];
  				double iper = (double)num[1].intValue()/(double)total;
  				double iheight = height * iper;
  				// if the height is less than one, we set it
  				// to one pixel
  				if (iheight < 1){
  					iheight = 1.0;
  				}
  				int ix = (count * 4) + xborder + 5;
  				int dheight = (int)(height - iheight);
  				g.setColor(Color.blue);
  				g.drawLine(ix -1,(int)height,ix -1,dheight);
  				g.drawLine(ix,(int)height,ix,dheight);
  				g.setColor(Color.black);
  				// draw a red line for 90% point
  				if (num[0].longValue() == ninety.longValue()){
  					g.setColor(Color.red);
  					g.drawLine(ix,(int)height,ix,55);
  					g.drawLine(ix,(int)35,ix,0);
  					g.drawString("90%",ix - 30,20);
  					g.drawString(String.valueOf(num[0].longValue()),ix + 8, 20);
  				}
  				// draw an orange line for 50% point
  				if (num[0].longValue() == fifty.longValue()){
  					g.setColor(Color.orange);
  					g.drawLine(ix,(int)height,ix,30);
  					g.drawString("50%",ix - 30,50);
  					g.drawString(String.valueOf(num[0].longValue()),ix + 8, 50);
  				}
  			}
          }
      }
  }
  
  
  
  1.1                  jakarta-jmeter/src/components/org/apache/jmeter/visualizers/DistributionGraphVisualizer.java
  
  Index: DistributionGraphVisualizer.java
  ===================================================================
  // $Header: /home/cvs/jakarta-jmeter/src/components/org/apache/jmeter/visualizers/DistributionGraphVisualizer.java,v 1.1 2004/05/28 02:35:12 woolfel Exp $
  /*
   * Copyright 2001-2004 The Apache Software Foundation.
   *
   * 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 org.apache.jmeter.visualizers;
  
  
  import java.awt.BorderLayout;
  import java.awt.Color;
  import java.awt.Component;
  import java.awt.Dimension;
  import java.awt.Image;
  import java.awt.event.ItemEvent;
  import java.awt.event.ItemListener;
  
  import javax.swing.BorderFactory;
  import javax.swing.Box;
  import javax.swing.JCheckBox;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  import javax.swing.JTextField;
  import javax.swing.border.BevelBorder;
  import javax.swing.border.Border;
  import javax.swing.border.EmptyBorder;
  
  import org.apache.jmeter.samplers.Clearable;
  import org.apache.jmeter.samplers.SampleResult;
  import org.apache.jmeter.util.JMeterUtils;
  import org.apache.jmeter.visualizers.gui.AbstractVisualizer;
  
  
  /**
   * This class implements the visualizer for displaying the distribution
   * graph. Distribution graphs are useful for standard benchmarks and
   * viewing the distribution of data points. Results tend to clump
   * together.
   *
   * Created     May 25, 2004
   * @version   $Revision: 
   */
  public class DistributionGraphVisualizer extends AbstractVisualizer
          implements ImageVisualizer, ItemListener, GraphListener, Clearable
  {
      GraphModel model;
      private JPanel graphPanel = null;
      private JTextField noSamplesField = null;
      String minute = JMeterUtils.getResString("minute");
  
      private DistributionGraph graph;
      private JTextField noteField;
      private int delay = 10;
      private int counter = 0;
      private int cwidth = 0;
      private int cheight = 0;
      
      /**
       * Constructor for the GraphVisualizer object.
       */
      public DistributionGraphVisualizer()
      {
          model = new GraphModel();
          model.addGraphListener(this);
          graph = new DistributionGraph(model);
          graph.setBackground(Color.white);
  		init();
      }
  
      /**
       * Gets the Image attribute of the GraphVisualizer object.
       *
       * @return   the Image value
       */
      public Image getImage()
      {
          Image result = graph.createImage(graph.getWidth(), graph.getHeight());
  
          graph.paintComponent(result.getGraphics());
  
          return result;
      }
  
      public synchronized void updateGui()
      {
      	if (graph.getWidth() < 10){
  			graph.setPreferredSize(new Dimension(getWidth() - 40, getHeight() - 160));
      	}
  		graphPanel.updateUI();
          graph.updateGui();
      }
  
      public synchronized void updateGui(Sample s)
      {
          // We have received one more sample
          if (delay == counter){
  			graphPanel.updateUI();
  			graph.updateGui(s);
  			counter = 0;
          } else {
          	counter++;
          }
      }
  
      public void add(SampleResult res)
      {
          model.addSample(res);
      }
  
      public String getLabelResource()
      {
          return "distribution_graph_title";
      }
  
      public void itemStateChanged(ItemEvent e)
      {
          this.graph.repaint();
      }
  
      public synchronized void clear()
      {
          this.graph.clear();
          model.clear();
          repaint();
      }
  
      public String toString()
      {
          return "Show the samples in a distribution graph";
      }
  
      /**
       * Initialize the GUI.
       */
      private void init()
      {
          this.setLayout(new BorderLayout());
  
          // MAIN PANEL
          Border margin = new EmptyBorder(10, 10, 5, 10);
  
          this.setBorder(margin);
  
          // Set up the graph with header, footer, Y axis and graph display
          JPanel graphPanel = new JPanel(new BorderLayout());
          graphPanel.add(createGraphPanel(), BorderLayout.CENTER);
          graphPanel.add(createGraphInfoPanel(), BorderLayout.SOUTH);
  
          // Add the main panel and the graph
          this.add(makeTitlePanel(), BorderLayout.NORTH);
          this.add(graphPanel, BorderLayout.CENTER);
      }
  
      // Methods used in creating the GUI
  
      /**
       * Creates a check box configured to be used to in the choose panel
       * allowing the user to select whether or not a particular kind of
       * graph data will be displayed.
       * 
       * @param labelResourceName the name of the label resource.
       *                This is used to look up the label text using
       *                {@link JMeterUtils#getResString(String)}.
       * @param color  the color used for the checkbox text. By
       *                convention this is the same color that is used
       *                to draw the graph and for the corresponding
       *                info field.
       *
       * @return       a checkbox allowing the user to select whether or
       *                not a kind of graph data will be displayed
       */
      private JCheckBox createChooseCheckBox(
          String labelResourceName,
          Color color)
      {
          JCheckBox checkBox = new JCheckBox(
                          JMeterUtils.getResString(labelResourceName));
          checkBox.setSelected(true);
          checkBox.addItemListener(this);
          checkBox.setForeground(color);
          return checkBox;
      }
  
  
      /**
       * Creates a scroll pane containing the actual graph of
       * the results.
       * 
       * @return a scroll pane containing the graph
       */
      private Component createGraphPanel()
      {
          graphPanel = new JPanel();
  		graphPanel.setBorder(BorderFactory.createBevelBorder(
  			BevelBorder.LOWERED,Color.lightGray,Color.darkGray));
          graphPanel.add(graph);
  		graphPanel.setBackground(Color.white);
          return graphPanel;
      }
  
      /**
       * Creates one of the fields used to display the graph's current
       * values.
       * 
       * @param color   the color used to draw the value. By convention
       *                 this is the same color that is used to draw the
       *                 graph for this value and in the choose panel.
       * @param length  the number of digits which the field should be
       *                 able to display
       * 
       * @return        a text field configured to display one of the
       *                 current graph values
       */
      private JTextField createInfoField(Color color, int length)
      {
          JTextField field = new JTextField(length);
          field.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
          field.setEditable(false);
          field.setForeground(color);
          field.setBackground(getBackground());
  
          // The text field should expand horizontally, but have
          // a fixed height
          field.setMaximumSize(new Dimension(
                      field.getMaximumSize().width,
                      field.getPreferredSize().height));
          return field;
      }
  
  
      /**
       * Creates a label for one of the fields used to display the graph's
       * current values. Neither the label created by this method or the
       * <code>field</code> passed as a parameter is added to the GUI here.
       * 
       * @param labelResourceName  the name of the label resource.
       *                This is used to look up the label text using
       *                {@link JMeterUtils#getResString(String)}.
       * @param field  the field this label is being created for.
       */
      private JLabel createInfoLabel(String labelResourceName, JTextField field)
      {
          JLabel label = new JLabel(
                  JMeterUtils.getResString(labelResourceName));
          label.setForeground(field.getForeground());
          label.setLabelFor(field);
          return label;
      }
  
  	/**
  	 * Creates the information Panel at the bottom
  	 * @return
  	 */
  	private Box createGraphInfoPanel()
  	{
  		Box graphInfoPanel = Box.createHorizontalBox();
  		this.noteField = new JTextField();
  		graphInfoPanel.add(
  			this.createInfoLabel("distribution_note1",this.noteField)
  		);
  		return graphInfoPanel;
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org