Attachment 'JMeterSummary.java'

Download

   1 import java.io.BufferedReader;
   2 import java.io.File;
   3 import java.io.FileNotFoundException;
   4 import java.io.FileReader;
   5 import java.io.IOException;
   6 import java.text.DecimalFormat;
   7 import java.util.HashMap;
   8 import java.util.Iterator;
   9 import java.util.LinkedList;
  10 import java.util.List;
  11 import java.util.Map;
  12 import java.util.TreeMap;
  13 import java.util.regex.Matcher;
  14 import java.util.regex.Pattern;
  15 
  16 /**
  17  * @author Andres.Galeano@Versatile.com
  18  */
  19 public class JMeterSummary {
  20     
  21     private static final String REG_EX =
  22         "<httpSample\\s*" + // Start element
  23           "t=\"([^\"]*)\"\\s*" + // GROUP_T
  24           "lt=\"([^\"]*)\"\\s*" + // GROUP_LT
  25           "ts=\"([^\"]*)\"\\s*" + // GROUP_TS
  26           "s=\"([^\"]*)\"\\s*" + // GROUP_S
  27           "lb=\"([^\"]*)\"\\s*" + // GROUP_LB
  28           "rc=\"([^\"]*)\"\\s*" + // GROUP_RC
  29           "rm=\"([^\"]*)\"\\s*" + // GROUP_RM
  30           "tn=\"([^\"]*)\"\\s*" + // GROUP_TN
  31           "dt=\"([^\"]*)\"\\s*"+ // GROUP_DT
  32         "/>"; // Finish element
  33     
  34     private static final int GROUP_ALL = 0;
  35     private static final int GROUP_T = 1;
  36     private static final int GROUP_LT = 2;
  37     private static final int GROUP_TS = 3;
  38     private static final int GROUP_S = 4;
  39     private static final int GROUP_LB = 5;
  40     private static final int GROUP_RC = 6;
  41     private static final int GROUP_RM = 7;
  42     private static final int GROUP_TN = 8;
  43     private static final int GROUP_DT = 9;
  44     
  45     private static final int DEFAULT_MILLIS_BUCKET = 500;
  46     
  47     protected final File _jmeterOutput;
  48     protected final int _millisPerBucket;
  49 
  50     /**
  51      */
  52     public static void main(String args[]) {
  53         try {
  54             int millisPerBucket;
  55             
  56             int argIndex = 0;
  57             
  58             if(args.length < 1) {
  59                 printUsage();
  60                 throw new IllegalArgumentException("Must provide a JMeter output file as an argument.");
  61             }
  62             
  63             String arg0 = args[argIndex++];
  64             if(arg0.contains("help")) {
  65                 printUsage();
  66                 return;
  67             }
  68             
  69             File outputFile = new File(arg0);
  70             if(!outputFile.exists()) {
  71                 throw new FileNotFoundException("File '" + outputFile + "' does not exist.");
  72             }
  73             
  74             if(args.length > argIndex) {
  75                 millisPerBucket = Integer.parseInt(args[argIndex++]);
  76             } else {
  77                 millisPerBucket = DEFAULT_MILLIS_BUCKET;
  78             }
  79             
  80             JMeterSummary instance = new JMeterSummary(outputFile, millisPerBucket);
  81             instance.run();
  82         } catch(Exception ex) {
  83             ex.printStackTrace();
  84         }
  85     } // end [main(String[])]
  86     
  87     /**
  88      */
  89     public static void printUsage() {
  90         System.out.println("Usage: " + JMeterSummary.class.getName() + " <JMeter Ouput File> [Millis Per Bucket]");
  91         System.out.println("  (By default hits are grouped in "+DEFAULT_MILLIS_BUCKET+" millis/bucket.)");
  92     }
  93 
  94     /**
  95      */
  96     public JMeterSummary(File inJmeterOutput, int inMillisPerBucket) {
  97         super();
  98         _jmeterOutput = inJmeterOutput;
  99         _millisPerBucket = inMillisPerBucket;
 100     }
 101     
 102     /**
 103      */
 104     public void run() throws IOException {
 105         Totals totalAll = new Totals();
 106         Map<String, Totals> totalUrlMap = new HashMap<String, Totals>(); // key = url, value = total
 107         
 108         Pattern p = Pattern.compile(REG_EX);
 109         
 110         BufferedReader inStream = new BufferedReader(new FileReader(_jmeterOutput));
 111         try {
 112             String line = inStream.readLine();
 113             while(line != null) {
 114                 Matcher m = p.matcher(line);
 115                 
 116                 if(m.find()) {
 117                     add(m, totalAll);
 118                     
 119                     String url = m.group(GROUP_LB);
 120                     Totals urlTotals = totalUrlMap.get(url);
 121                     if(urlTotals == null) {
 122                         urlTotals = new Totals();
 123                         totalUrlMap.put(url, urlTotals);
 124                     }
 125                     add(m, urlTotals);
 126                 }
 127                 
 128                 line = inStream.readLine();
 129             }
 130             
 131         } finally {
 132             inStream.close();
 133         }
 134         
 135         if(totalAll.count == 0) {
 136             System.out.println("No results found!");
 137             return;
 138         }
 139         
 140         System.out.println("All Urls:");
 141         System.out.println(totalAll.toBasicString());
 142         System.out.println(totalAll.toAdvancedString());
 143         System.out.println("");
 144         
 145         Iterator iter = totalUrlMap.entrySet().iterator();
 146         while(iter.hasNext()) {
 147             
 148             Map.Entry entry = (Map.Entry)iter.next();
 149             String url = (String)entry.getKey();
 150             Totals totals = (Totals)entry.getValue();
 151             
 152             System.out.println("URL: " + url);
 153             System.out.println(totals.toBasicString());
 154             System.out.println("");
 155         }
 156     } // end [run()]
 157 
 158     /**
 159      */
 160     private void add(Matcher inM, Totals inTotal) {
 161         inTotal.count ++;
 162         long timeStamp = Long.parseLong(inM.group(GROUP_TS));
 163         inTotal.last_ts = Math.max(inTotal.last_ts, timeStamp);
 164         inTotal.first_ts = Math.min(inTotal.first_ts, timeStamp);
 165         
 166         int time = Integer.parseInt(inM.group(GROUP_T));
 167         inTotal.total_t += time;
 168         inTotal.max_t = Math.max(inTotal.max_t, time);
 169         inTotal.min_t = Math.min(inTotal.min_t, time);
 170         
 171         int conn = time - Integer.parseInt(inM.group(GROUP_LT));
 172         inTotal.total_conn += conn;
 173         inTotal.max_conn = Math.max(inTotal.max_conn, conn);
 174         inTotal.min_conn = Math.min(inTotal.min_conn, conn);
 175         
 176         String rc = inM.group(GROUP_RC);
 177         Integer count = inTotal.rcMap.get(rc);
 178         if(count == null) {
 179             count = new Integer(0);
 180         }
 181         inTotal.rcMap.put(rc, new Integer(count.intValue() + 1));
 182         
 183         Integer bucket = new Integer(time / _millisPerBucket);
 184         count = inTotal.millisMap.get(bucket);
 185         if(count == null) {
 186             count = new Integer(0);
 187         }
 188         inTotal.millisMap.put(bucket, new Integer(count.intValue() + 1));
 189         
 190         if(!inM.group(GROUP_S).equalsIgnoreCase("true")) {
 191             inTotal.failures ++;
 192         }
 193     } // end [add(Matcher, Totals)]
 194     
 195     /**
 196      * @author Andres.Galeano@Versatile.com
 197      */
 198     private class Totals {
 199         private static final String DECIMAL_PATTERN = "#,##0.0##";
 200         private static final double MILLIS_PER_SECOND = 1000.0;
 201         
 202         public int count = 0;
 203         public int total_t = 0;
 204         public int max_t = 0; // will choose largest
 205         public int min_t = Integer.MAX_VALUE; // will choose smallest
 206         public int total_conn = 0;
 207         public int max_conn = 0;  // will choose largest
 208         public int min_conn = Integer.MAX_VALUE; // will choose smallest
 209         public int failures = 0;
 210         public long first_ts = Long.MAX_VALUE; // will choose smallest
 211         public long last_ts = 0;  // will choose largest
 212         public Map<String, Integer> rcMap = new HashMap<String, Integer>(); // key rc, value count
 213         public Map<Integer, Integer> millisMap = new TreeMap<Integer, Integer>(); // key bucket Integer, value count
 214         
 215         public Totals() {
 216         }
 217         
 218         public String toBasicString() {
 219             
 220             DecimalFormat df = new DecimalFormat(DECIMAL_PATTERN);
 221             
 222             List<String> millisStr = new LinkedList<String>();
 223             
 224             Iterator iter = millisMap.entrySet().iterator();
 225             while(iter.hasNext()) {
 226                 Map.Entry millisEntry = (Map.Entry)iter.next();
 227                 Integer bucket = (Integer)millisEntry.getKey();
 228                 Integer bucketCount = (Integer)millisEntry.getValue();
 229                 
 230                 int minMillis = bucket.intValue() * _millisPerBucket;
 231                 int maxMillis = (bucket.intValue() + 1) * _millisPerBucket;
 232                 
 233                 millisStr.add(
 234                   df.format(minMillis/MILLIS_PER_SECOND)+" s "+
 235                   "- "+
 236                   df.format(maxMillis/MILLIS_PER_SECOND)+" s "+
 237                   "= " + bucketCount);
 238             }
 239             
 240             return
 241               "cnt: " + count + ", "+
 242               "avg t: " + (total_t/count) + " ms, "+
 243               "max t: " + max_t + " ms, "+
 244               "min t: " + min_t + " ms, "+
 245               "result codes: " + rcMap + ", "+
 246               "failures: "+failures+", "+
 247               "cnt by time: " + millisStr + "";
 248             
 249         } // end [Totals.toString()]
 250         
 251         public String toAdvancedString() {
 252             double secondsElaspsed = (last_ts - first_ts) / MILLIS_PER_SECOND;
 253             long countPerSecond = Math.round(count / secondsElaspsed);
 254             
 255             return
 256                 "avg conn: " + (total_conn/count) + " ms, "+
 257                 "max conn: " + max_conn + " ms, "+
 258                 "min conn: " + min_conn + " ms, " +
 259                 "elapsed seconds: " + Math.round(secondsElaspsed) + " s, " +
 260                 "cnt per second: " + countPerSecond ;
 261         }
 262         
 263     } // end [class Totals]
 264 
 265 } // end [class JMeterSummary]
 266 

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.