Author: sebb
Date: Thu Dec  6 15:25:13 2007
New Revision: 601911

URL: http://svn.apache.org/viewvc?rev=601911&view=rev
Log:
Can specify list of variable names to be written to JTL files (CSV and XML 
format)

Modified:
    jakarta/jmeter/trunk/bin/jmeter.properties
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/control/TransactionController.java
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSaveConfiguration.java
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java
    
jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/converters/SampleResultConverter.java
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
    jakarta/jmeter/trunk/xdocs/changes.xml
    jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
    jakarta/jmeter/trunk/xdocs/usermanual/listeners.xml

Modified: jakarta/jmeter/trunk/bin/jmeter.properties
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/bin/jmeter.properties?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- jakarta/jmeter/trunk/bin/jmeter.properties (original)
+++ jakarta/jmeter/trunk/bin/jmeter.properties Thu Dec  6 15:25:13 2007
@@ -321,6 +321,12 @@
 #jmeter.save.saveservice.default_delimiter=\t
 #jmeter.save.saveservice.print_field_names=false
 
+# Optional list of JMeter variable names whose values are to be saved in the 
result data files.
+# Use commas to separate the names. For example:
+#sample_variables=SESSION_ID,REFERENCE
+# N.B. The current implementation saves the values in XML as attributes,
+# so the names must be valid XML names.
+
 # Optional xml processing instruction for line 2 of the file:
 #jmeter.save.saveservice.xml_pi=<?xml-stylesheet type="text/xsl" 
href="../extras/jmeter-results-detail-report_21.xsl"?>
 

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/control/TransactionController.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/control/TransactionController.java?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/control/TransactionController.java
 (original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/control/TransactionController.java
 Thu Dec  6 15:25:13 2007
@@ -170,7 +170,7 @@
                                if (pack == null) {
                                        log.warn("Could not fetch 
SamplePackage");
                                } else {
-                    SampleEvent event = new SampleEvent(res, 
threadContext.getThreadGroup().getName());
+                    SampleEvent event = new SampleEvent(res, 
threadContext.getThreadGroup().getName(),threadVars);
                     // We must set res to null now, before sending the event 
for the transaction,
                     // so that we can ignore that event in our sampleOccured 
method 
                     res = null;

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSaveConfiguration.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSaveConfiguration.java?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSaveConfiguration.java
 (original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSaveConfiguration.java
 Thu Dec  6 15:25:13 2007
@@ -59,7 +59,7 @@
  *
  */
 public class SampleSaveConfiguration implements Cloneable, Serializable {
-       private static final long serialVersionUID = 6L;
+       private static final long serialVersionUID = 7L;
 
        // ---------------------------------------------------------------------
        // PROPERTY FILE CONSTANTS
@@ -384,7 +384,19 @@
 
        // Don't save this, as not settable via GUI
        private String delimiter = _delimiter;
+       
+       // Don't save this - only needed for processing CSV headers currently
+       private transient int varCount = 0;
+       
        private static final SampleSaveConfiguration _static = new 
SampleSaveConfiguration();
+
+       public int getVarCount() { // Only for use by CSVSaveService
+               return varCount;
+       }
+
+       public void setVarCount(int varCount) { // Only for use by 
CSVSaveService
+               this.varCount = varCount;
+       }
 
        // Give access to initial configuration
        public static SampleSaveConfiguration staticConfig() {

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java 
(original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/CSVSaveService.java 
Thu Dec  6 15:25:13 2007
@@ -86,7 +86,10 @@
     private static final String CSV_LATENCY = "Latency"; // $NON-NLS-1$
     private static final String CSV_ENCODING = "Encoding"; // $NON-NLS-1$
     private static final String CSV_HOSTNAME = "Hostname"; // $NON-NLS-1$
-    
+
+    // Used to enclose variable name labels, to distinguish from any of the 
above labels
+       private static final String VARIABLE_NAME_QUOTE_CHAR = "\"";  // 
$NON-NLS-1$
+
     // Initial config from properties
        static private final SampleSaveConfiguration _saveConfig = 
SampleSaveConfiguration.staticConfig();
 
@@ -120,6 +123,7 @@
                        long lineNumber=1;
                        SampleSaveConfiguration saveConfig = 
CSVSaveService.getSampleSaveConfiguration(line,filename);
                        if (saveConfig == null) {// not a valid header
+                               log.info(filename+" does not appear to have a 
valid header. Using default configuration.");
                                saveConfig = (SampleSaveConfiguration) 
resultCollector.getSaveConfig().clone(); // may change the format later
                                dataReader.reset(); // restart from beginning
                                lineNumber = 0;
@@ -148,7 +152,7 @@
      * @param lineNumber - line number for error reporting
      * @return SampleResult
      * 
-     * @deprecated Does not handle quoted strings
+     * @deprecated Does not handle quoted strings; use [EMAIL PROTECTED] 
#processSamples(String, Visualizer, ResultCollector)} instead
      * 
      * @throws JMeterError
      */
@@ -174,7 +178,7 @@
      * 
      * @throws JMeterError
      */
-    public static SampleEvent makeResultFromDelimitedString(
+    private static SampleEvent makeResultFromDelimitedString(
                final String[] parts, 
                final SampleSaveConfiguration saveConfig, // may be updated
                final long lineNumber) {
@@ -315,6 +319,10 @@
                 hostname = parts[i++];
             }
             
+            if (i + saveConfig.getVarCount() < parts.length){
+               log.warn("Line: "+lineNumber+". Found "+parts.length+" fields, 
expected "+i+". Extra fields have been ignored.");
+            }
+
                } catch (NumberFormatException e) {
                        log.warn("Error parsing field '" + field + "' at line " 
+ lineNumber + " " + e);
                        throw new JMeterError(e);
@@ -435,6 +443,13 @@
             text.append(delim);
         }
 
+        for (int i = 0; i < SampleEvent.getVarCount(); i++){
+               text.append(VARIABLE_NAME_QUOTE_CHAR);
+               text.append(SampleEvent.getVarName(i));
+               text.append(VARIABLE_NAME_QUOTE_CHAR);
+            text.append(delim);
+        }
+
         String resultString = null;
                int size = text.length();
                int delSize = delim.length();
@@ -496,7 +511,8 @@
                        // word followed by 0 or more repeats of (non-word char 
+ word)
                        // where the non-word char (\2) is the same
                        // e.g.  abc|def|ghi but not abd|def~ghi
-                               .getPattern("\\w+((\\W)\\w+)?(\\2\\w+)*", // 
$NON-NLS-1$
+                               
.getPattern("\\w+((\\W)\\w+)?(\\2\\w+)*(\\2\"\\w+\")*", // $NON-NLS-1$
+                                               // last entries may be quoted 
strings
                                        Perl5Compiler.READ_ONLY_MASK);
                        if (matcher.matches(input, pattern)) {
                                delim = matcher.getMatch().group(2);
@@ -511,15 +527,24 @@
                // We know the column names all exist, so create the config 
                SampleSaveConfiguration saveConfig=new 
SampleSaveConfiguration(false);
                
+               int varCount = 0;
                for(int i=0;i<parts.length;i++){
-                       Functor set = (Functor) 
headerLabelMethods.get(parts[i]);
-                       set.invoke(saveConfig,new Boolean[]{Boolean.TRUE});
+                       String label = parts[i];
+                       if (isVariableName(label)){
+                               varCount++;
+                       } else {
+                               Functor set = (Functor) 
headerLabelMethods.get(label);
+                               set.invoke(saveConfig,new 
Boolean[]{Boolean.TRUE});
+                       }
                }
 
                if (delim != null){
                        log.warn("Default delimiter 
'"+_saveConfig.getDelimiter()+"' did not work; using alternate '"+delim+"' for 
reading "+filename);
                        saveConfig.setDelimiter(delim);
                }
+               
+               saveConfig.setVarCount(varCount);
+               
                return saveConfig;
        }
 
@@ -529,6 +554,11 @@
                // Check if the line is a header
                for(int i=0;i<parts.length;i++){
                        final String label = parts[i];
+                       // Check for Quoted variable names
+                       if (isVariableName(label)){
+                               previous=Integer.MAX_VALUE; // they are always 
last
+                               continue;
+                       }
                        int current = headerLabelMethods.indexOf(label);
                        if (current == -1){
                                return null; // unknown column name
@@ -543,6 +573,18 @@
        }
 
        /**
+        * Check if the label is a variable name, i.e. is it enclosed in 
double-quotes?
+        * 
+        * @param label column name from CSV file
+        * @return if the label is enclosed in double-quotes
+        */
+       private static boolean isVariableName(final String label) {
+               return label.length() > 2
+                   && label.startsWith(VARIABLE_NAME_QUOTE_CHAR)
+                   && label.endsWith(VARIABLE_NAME_QUOTE_CHAR);
+       }
+
+       /**
      * Method will save aggregate statistics as CSV. For now I put it here.
      * Not sure if it should go in the newer SaveService instead of here.
      * if we ever decide to get rid of this class, we'll need to move this
@@ -613,6 +655,7 @@
                // These methods handle parameters that could contain 
delimiters or escapes:
                public void append(String s){
                        addDelim();
+                       //if (s == null) return;
                        sb.append(escapeDelimiters(s,specials));
                }
                public void append(Object obj){
@@ -730,6 +773,10 @@
     
         if (saveConfig.saveHostname()) {
             text.append(event.getHostname());
+        }
+
+        for (int i=0; i < SampleEvent.getVarCount(); i++){
+               text.append(event.getVarValue(i));
         }
 
        return text.toString();

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/converters/SampleResultConverter.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/converters/SampleResultConverter.java?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/converters/SampleResultConverter.java
 (original)
+++ 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/save/converters/SampleResultConverter.java
 Thu Dec  6 15:25:13 2007
@@ -265,11 +265,16 @@
            writer.addAttribute(ATT_GRP_THRDS, 
String.valueOf(res.getGroupThreads()));
            writer.addAttribute(ATT_ALL_THRDS, 
String.valueOf(res.getAllThreads()));
         }
+        SampleEvent event = (SampleEvent) 
context.get(SaveService.SAMPLE_EVENT_OBJECT);
         if (save.saveHostname()){
-            SampleEvent event = (SampleEvent) 
context.get(SaveService.SAMPLE_EVENT_OBJECT);
             if (event != null) {
                writer.addAttribute(ATT_HOSTNAME, event.getHostname());         
             }
+        }
+        if (event != null) {
+               for (int i = 0; i < SampleEvent.getVarCount(); i++){
+                  writer.addAttribute(SampleEvent.getVarName(i), 
ConversionHelp.encode(event.getVarValue(i)));
+               }
         }
        }
 

Modified: 
jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java 
(original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java 
Thu Dec  6 15:25:13 2007
@@ -286,9 +286,8 @@
                             // Get the sampler ready to sample
                             SamplePackage pack = 
compiler.configureSampler(sam);
 
-                                                   // Hack: save the package 
for any transaction
-                                                   // controllers
-                                                   
threadContext.getVariables().putObject(PACKAGE_OBJECT, pack);
+                                                   // Hack: save the package 
for any transaction controllers
+                                                       
threadVars.putObject(PACKAGE_OBJECT, pack);
 
                             delay(pack.getTimers());
                             Sampler sampler = pack.getSampler();
@@ -572,7 +571,7 @@
        }
 
        private void notifyListeners(List listeners, SampleResult result) {
-               SampleEvent event = new SampleEvent(result, 
threadGroup.getName());
+               SampleEvent event = new SampleEvent(result, 
threadGroup.getName(), threadVars);
                notifier.notifyListeners(event, listeners);
 
        }

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Thu Dec  6 15:25:13 2007
@@ -63,6 +63,7 @@
 <li>Reduce class loading in non-GUI mode by only looking for Functions in 
class names
 that contain '.functions.' and don't contain '.gui.'</li>
 <li>Bug 43379 - Switch Controller now supports selection by name as well as 
number</li>
+<li>Can specify list of variable names to be written to JTL files (CSV and XML 
format)</li>
 </ul>
 
 <h4>Non-functional changes</h4>

Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Thu Dec  6 
15:25:13 2007
@@ -1696,6 +1696,10 @@
 </ul>
 <p>To minimise the amount of memory needed, use the Simple Data Writer, and 
use the CSV format.</p>
 <p>
+<note>
+Versions of JMeter after 2.3.1 allow JMeter variables to be saved to the 
output files.
+This can only be specified using a property. See the following link for 
details.
+</note>
 For full details on setting up the default items to be saved
 see the <a href="listeners.html#defaults">Listener Default Configuration</a> 
documentation.
 For details of the contents of the output files,

Modified: jakarta/jmeter/trunk/xdocs/usermanual/listeners.xml
URL: 
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/listeners.xml?rev=601911&r1=601910&r2=601911&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/listeners.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/listeners.xml Thu Dec  6 15:25:13 2007
@@ -165,17 +165,29 @@
 
 #jmeter.save.saveservice.print_field_names=false
 
+# Optional list of JMeter variable names whose values are to be saved in the 
result data files.
+# Use commas to separate the names. For example:
+#sample_variables=SESSION_ID,REFERENCE
+# N.B. The current implementation saves the values in XML as attributes,
+# so the names must be valid XML names.
+
 # Optional xml processing instruction for line 2 of the file:
 #jmeter.save.saveservice.xml_pi=&amp;lt;?xml-stylesheet type="text/xsl" 
href="sample.xsl"?>
 </pre>
 </code></p>
 <p>
-The date format to be used for the timestamp_format is described in <A
+The date format to be used for the timestamp_format is described in <a
 HREF="http://java.sun.com/j2se/1.4/docs/api/java/text/SimpleDateFormat.html";>
-<B>SimpleDateFormat</B></A>.
+<b>SimpleDateFormat</b></a>.
 Bear in mind that choosing a date format other than "ms" is likely to
 make it impossible for JMeter to interpret the value when it is read
 in later for viewing purposes.</p>
+<p>
+Versions of JMeter after 2.3.1 allow one to use the <b>sample_variables</b> 
+property to define a list of additional JMeter variables which are to be saved 
with
+each sample in the JTL files. The values are written to CSV files as 
additional columns,
+and as additional attributes in XML files.
+</p>
 </section>
 
 <section name="&sect-num;.2 non-GUI (batch) test runs" anchor="batch">
@@ -197,6 +209,12 @@
 This file is recreated each time, so if you want to keep the log files for 
each run, 
 you will need to rename it using the -j option as above. The -j option was 
added in version 2.3.
 </p>
+<p>Versions of JMeter after 2.3.1 support variables in the log file name.
+If the filename contains  paired single-quotes, then the name is processed
+as a SimpleDateFormat format applied to the current date, for example:
+<b>log_file='jmeter_'yyyyMMddHHmmss'.tmp'</b>. 
+This can be used to generate a unique name for each test run.
+</p>
 </section>
 
 <section name="&sect-num;.3 Resource usage" anchor="resources">
@@ -240,6 +258,7 @@
 <li>SampleCount - number of samples (1, unless multiple samples are 
aggregated)</li>
 <li>ErrorCount - number of errors (0 or 1, unless multiple samples are 
aggregated)</li>
 <li>Hostname where the sample was generated</li>
+<li>Variables, if specified</li>
 </ul>
 
 </section>
@@ -391,11 +410,17 @@
 <tr><td> t</td><td>Elapsed time (milliseconds)</td></tr>
 <tr><td>tn</td><td>Thread Name</td></tr>
 <tr><td>ts</td><td>timeStamp (milliseconds since midnight Jan 1, 1970 
UTC)</td></tr>
+<tr><td>varname</td><td>Value of the named variable (versions of JMeter after 
2.3.1)</td></tr>
 </table>
 <p>
 Versions 2.1 and 2.1.1 of JMeter saved the Response Code as "rs", but read it 
back expecting to find "rc".
 This has been corrected so that it is always saved as "rc"; either "rc" or 
"rs" can be read.
 </p>
+<note>
+Versions of JMeter after 2.3.1 allow additional variables to be saved with the 
test plan.
+Currently, the variables are saved as additional attributes. 
+The testplan variable name is used as the attribute name.
+</note>
 </section>
 
 <section name="&sect-num;.8 Saving response data" anchor="saving">



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to