/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.reporters; import java.text.DecimalFormat; import org.apache.jmeter.samplers.SampleResult; /** * <p> * Running sample data container. Just instantiate a new instance of this * class, and then call {@link #addSample(SampleResult)} a few times, and pull * the stats out with whatever methods you prefer. * </p> * <p> * Please note that this class is not thread-safe. * The calling class is responsible for ensuring thread safety if required. * The caller needs to synchronize access in order to ensure that variables are consistent. * </p> * @since 2.13 */ class SummariserRunningSample { private final DecimalFormat errorFormatter = new DecimalFormat("#0.00%"); // $NON-NLS-1$ private long counter; private long runningSum; private long max; private long min; private long errorCount; private long startTime; private long endTime; private final String label; /** * @param label the label of this component */ public SummariserRunningSample(String label) { this.label = label; init(); } /** * Copy constructor * @param src the instance to copy */ public SummariserRunningSample(SummariserRunningSample src) { label = src.label; counter = src.counter; errorCount = src.errorCount; startTime = src.startTime; endTime = src.endTime; max = src.max; min = src.min; runningSum = src.runningSum; } private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final) counter = 0L; runningSum = 0L; max = Long.MIN_VALUE; min = Long.MAX_VALUE; errorCount = 0L; startTime = System.currentTimeMillis(); endTime = startTime; } /** * Clear at every interval */ public void clear() { init(); } /** * Used for delta * @param rs {@link SummariserRunningSample} */ public void addSample(SummariserRunningSample rs) { counter += rs.counter; errorCount += rs.errorCount; runningSum += rs.runningSum; if (max < rs.max) { max = rs.max; } if (min > rs.min) { min = rs.min; } // We want end time to be current time so sample rates reflect real time endTime = System.currentTimeMillis(); } /** * Used for each SampleResult * @param res {@link SampleResult} */ public void addSample(SampleResult res) { counter += res.getSampleCount(); errorCount += res.getErrorCount(); long aTimeInMillis = res.getTime(); runningSum += aTimeInMillis; if (aTimeInMillis > max) { max = aTimeInMillis; } if (aTimeInMillis < min) { min = aTimeInMillis; } // We want end time to be current time so sample rates reflect real time endTime = System.currentTimeMillis(); } /** * Returns the number of samples that have been recorded by this instance of * the {@link SummariserRunningSample} class. * * @return the number of samples that have been recorded by this instance of * the {@link SummariserRunningSample} class. */ public long getNumSamples() { return counter; } /** * Get the elapsed time for the samples * * @return how long the samples took */ public long getElapsed() { if (counter == 0) { return 0;// No samples collected ... } return endTime - startTime; } /** * Returns the throughput associated to this sampler in requests per second. * * @return throughput associated to this sampler */ public double getRate() { if (counter == 0) { return 0.0;// No samples collected ... } long howLongRunning = endTime - startTime; if (howLongRunning == 0) { return Double.MAX_VALUE; } return (double) counter / howLongRunning * 1000.0; } /** * Returns the average time in milliseconds that samples ran in. * * @return the average time in milliseconds that samples ran in. */ public long getAverage() { if (counter == 0) { return 0; } return runningSum / counter; } /** * @return errorCount */ public long getErrorCount() { return errorCount; } /** * Returns a String which represents the percentage of sample errors that * have occurred. ("0.00%" through "100.00%") * * @return a String which represents the percentage of sample errors that * have occurred. */ public String getErrorPercentageString() { return errorFormatter.format(getErrorPercentage()); } /** * Returns the raw double value of the percentage of samples with errors * that were recorded. (Between 0.0 and 1.0) If you want a nicer return * format, see {@link #getErrorPercentageString()}. * * @return the raw double value of the percentage of samples with errors * that were recorded. Returns 0.0 if there are no samples */ public double getErrorPercentage() { if (counter == 0) { return 0.0; } double rval = (double) errorCount / (double) counter; return rval; } /** * Returns the time in milliseconds of the slowest sample. * * @return the time in milliseconds of the slowest sample. */ public long getMax() { return max; } /** * Returns the time in milliseconds of the quickest sample. * * @return the time in milliseconds of the quickest sample. */ public long getMin() { return min; } /** * Set end time */ public void setEndTime() { endTime = System.currentTimeMillis(); } }