001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations
015: * under the License.
016: *
017: */
018:
019: package org.apache.jmeter.visualizers;
020:
021: import java.awt.Color;
022: import java.awt.Dimension;
023: import java.awt.Graphics;
024: import java.awt.Rectangle;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import javax.swing.JComponent;
029: import javax.swing.Scrollable;
030: import javax.swing.SwingUtilities;
031:
032: import org.apache.jmeter.gui.util.JMeterColor;
033: import org.apache.jmeter.samplers.Clearable;
034: import org.apache.jorphan.logging.LoggingManager;
035: import org.apache.log.Logger;
036:
037: /**
038: * Implements a simple graph for displaying performance results.
039: *
040: */
041: public class Graph extends JComponent implements Scrollable, Clearable {
042: private static Logger log = LoggingManager.getLoggerForClass();
043:
044: private boolean wantData = true;
045:
046: private boolean wantAverage = true;
047:
048: private boolean wantDeviation = true;
049:
050: private boolean wantThroughput = true;
051:
052: private boolean wantMedian = true;
053:
054: private SamplingStatCalculator model;
055:
056: private static int width = 2000;
057:
058: private long graphMax = 1;
059:
060: private double throughputMax = 1;
061:
062: /**
063: * Constructor for the Graph object.
064: */
065: public Graph() {
066: this .setPreferredSize(new Dimension(width, 100));
067: }
068:
069: /**
070: * Constructor for the Graph object.
071: */
072: public Graph(SamplingStatCalculator model) {
073: this ();
074: setModel(model);
075: }
076:
077: /**
078: * Sets the Model attribute of the Graph object.
079: */
080: private void setModel(Object model) {
081: this .model = (SamplingStatCalculator) model;
082: repaint();
083: }
084:
085: /**
086: * Gets the PreferredScrollableViewportSize attribute of the Graph object.
087: *
088: * @return the PreferredScrollableViewportSize value
089: */
090: public Dimension getPreferredScrollableViewportSize() {
091: return this .getPreferredSize();
092: // return new Dimension(width, 400);
093: }
094:
095: /**
096: * Gets the ScrollableUnitIncrement attribute of the Graph object.
097: *
098: * @return the ScrollableUnitIncrement value
099: */
100: public int getScrollableUnitIncrement(Rectangle visibleRect,
101: int orientation, int direction) {
102: return 5;
103: }
104:
105: /**
106: * Gets the ScrollableBlockIncrement attribute of the Graph object.
107: *
108: * @return the ScrollableBlockIncrement value
109: */
110: public int getScrollableBlockIncrement(Rectangle visibleRect,
111: int orientation, int direction) {
112: return (int) (visibleRect.width * .9);
113: }
114:
115: /**
116: * Gets the ScrollableTracksViewportWidth attribute of the Graph object.
117: *
118: * @return the ScrollableTracksViewportWidth value
119: */
120: public boolean getScrollableTracksViewportWidth() {
121: return false;
122: }
123:
124: /**
125: * Gets the ScrollableTracksViewportHeight attribute of the Graph object.
126: *
127: * @return the ScrollableTracksViewportHeight value
128: */
129: public boolean getScrollableTracksViewportHeight() {
130: return true;
131: }
132:
133: /**
134: * Clears this graph.
135: */
136: public void clearData() {
137: graphMax = 1;
138: throughputMax = 1;
139: }
140:
141: public void enableData(boolean value) {
142: this .wantData = value;
143: }
144:
145: public void enableAverage(boolean value) {
146: this .wantAverage = value;
147: }
148:
149: public void enableMedian(boolean value) {
150: this .wantMedian = value;
151: }
152:
153: public void enableDeviation(boolean value) {
154: this .wantDeviation = value;
155: }
156:
157: public void enableThroughput(boolean value) {
158: this .wantThroughput = value;
159: }
160:
161: public void updateGui(final Sample oneSample) {
162: long h = model.getPercentPoint((float) 0.90).longValue();
163: boolean repaint = false;
164: if ((oneSample.getCount() % 20 == 0 || oneSample.getCount() < 20)
165: && h > (graphMax * 1.2) || graphMax > (h * 1.2)) {
166: if (h >= 1) {
167: graphMax = h;
168: } else {
169: graphMax = 1;
170: }
171: repaint = true;
172: }
173: if (model.getMaxThroughput() > throughputMax) {
174: throughputMax = model.getMaxThroughput() * 1.3;
175: repaint = true;
176: }
177: if (repaint) {
178: repaint();
179: return;
180: }
181: final int xPos = model.getCount();
182:
183: SwingUtilities.invokeLater(new Runnable() {
184: public void run() {
185: Graphics g = getGraphics();
186:
187: if (g != null) {
188: drawSample(xPos, oneSample, g);
189: }
190: }
191: });
192: }
193:
194: public void paintComponent(Graphics g) {
195: super .paintComponent(g);
196:
197: List samples = model.getSamples();
198: synchronized (samples) {
199: Iterator e = samples.iterator();
200:
201: for (int i = 0; e.hasNext(); i++) {
202: Sample s = (Sample) e.next();
203:
204: drawSample(i, s, g);
205: }
206: }
207: }
208:
209: private void drawSample(int x, Sample oneSample, Graphics g) {
210: // int width = getWidth();
211: int height = getHeight();
212: log.debug("Drawing a sample at " + x);
213: if (wantData) {
214: int data = (int) (oneSample.getData() * height / graphMax);
215:
216: if (oneSample.isSuccess()) {
217: g.setColor(Color.black);
218: } else {
219: g.setColor(JMeterColor.YELLOW);
220: }
221: g.drawLine(x % width, height - data, x % width, height
222: - data - 1);
223: log.debug("Drawing coords = " + (x % width) + ","
224: + (height - data));
225: }
226:
227: if (wantAverage) {
228: int average = (int) (oneSample.getAverage() * height / graphMax);
229:
230: g.setColor(Color.blue);
231: g.drawLine(x % width, height - average, x % width, (height
232: - average - 1));
233: }
234:
235: if (wantMedian) {
236: int median = (int) (oneSample.getMedian() * height / graphMax);
237:
238: g.setColor(JMeterColor.purple);
239: g.drawLine(x % width, height - median, x % width, (height
240: - median - 1));
241: }
242:
243: if (wantDeviation) {
244: int deviation = (int) (oneSample.getDeviation() * height / graphMax);
245:
246: g.setColor(Color.red);
247: g.drawLine(x % width, height - deviation, x % width,
248: (height - deviation - 1));
249: }
250: if (wantThroughput) {
251: int throughput = (int) (oneSample.getThroughput() * height / throughputMax);
252:
253: g.setColor(JMeterColor.dark_green);
254: g.drawLine(x % width, height - throughput, x % width,
255: (height - throughput - 1));
256: }
257: }
258:
259: /**
260: * @return Returns the graphMax.
261: */
262: public long getGraphMax() {
263: return graphMax;
264: }
265: }
|